diff --git a/h.c b/h.c index 73d2f73742babccdad1da15bc2b8182668a88aea..e0e2d48caa423377822b3f5342c3f6e35d8cdf6c 100644 --- a/h.c +++ b/h.c @@ -312,17 +312,24 @@ static bool handle_http_request(int sockfd, struct User* user_arr[]) // assume the only valid request URI is "/" but it can be modified to accept more files if (*curr == ' ' || *curr == '?') + if(strstr(buff, "quit=Quit") != NULL) { + simple_load_html("7_gameover.html",sockfd,buff,n,curr_user); + curr_user->stage=100; + curr_user->isOnline=0; + + } + //Stage1: when user name is not registed - if (curr_user->stage==0){ + else if (curr_user->stage==0){ if (method==GET) { - printf("curr_user->username%s == %d\n", curr_user->username,curr_user->username==NULL); + //printf("curr_user->username%s == %d\n", curr_user->username,curr_user->username==NULL); simple_load_html("1_intro.html",sockfd,buff,n,curr_user); } else if (method == POST) { - printf("curr_user->username%s == %d\n", curr_user->username,curr_user->username==NULL); + //printf("curr_user->username%s == %d\n", curr_user->username,curr_user->username==NULL); // locate the username, it is safe to do so in this sample code, but usually the result is expected to be // copied to another buffer using strcpy or strncpy to ensure that it will not be overwritten. char * user = strstr(buff, "user=") + 5; @@ -341,19 +348,12 @@ static bool handle_http_request(int sockfd, struct User* user_arr[]) else if(curr_user->stage==1) { - // quit: user not online - if(strstr(buff, "quit=Quit") != NULL) - { curr_user->isOnline=0; - simple_load_html("7_gameover.html",sockfd,buff,n,curr_user); - curr_user->stage=3; - } // start is the only GET mathod for ther stage 1 - else if (method == GET) + if (method == GET) { curr_user->isOnline=1; - simple_load_html("3_first_turn.html",sockfd,buff,n,curr_user); curr_user->stage =2; - curr_user->isOnline=1; + simple_load_html("3_first_turn.html",sockfd,buff,n,curr_user); } } @@ -363,15 +363,12 @@ static bool handle_http_request(int sockfd, struct User* user_arr[]) char * new_guess = strstr(buff, "keyword=") + 8; - if(strstr(buff, "quit=Quit") != NULL) - { curr_user->isOnline=0; - simple_load_html("7_gameover.html",sockfd,buff,n,curr_user); - clear_user_keyword(curr_user); - } - else if (the_other_user(curr_user, user_arr)->stage==3){ + if (the_other_user(curr_user, user_arr)->stage==100){ + printf("%dbhjbjhbjhbhjbjasdc\n", curr_user->stage); simple_load_html("7_gameover.html",sockfd,buff,n,curr_user); clear_user_keyword(curr_user); + } else if(the_other_user(curr_user, user_arr)->isOnline==0){ @@ -385,9 +382,11 @@ static bool handle_http_request(int sockfd, struct User* user_arr[]) { simple_load_html("6_endgame.html",sockfd,buff,n,curr_user); clear_user_keyword(curr_user); + curr_user->isOnline=0; + } else{ - curr_user->stage =2; + printf("curr_user->n_word%d\n",curr_user->n_word ); // remember new guess record_keyword(curr_user, new_guess); diff --git a/img.c b/img.c new file mode 100644 index 0000000000000000000000000000000000000000..82530cd5a881323f7a4afd7fac95317c399a9457 --- /dev/null +++ b/img.c @@ -0,0 +1,477 @@ +/* +** http-server.c +*/ + +#include <errno.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <arpa/inet.h> +#include <fcntl.h> +#include <netdb.h> +#include <netinet/in.h> +#include <strings.h> +#include <sys/select.h> +#include <sys/sendfile.h> + +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + + +#define MAX_BUFF 2049 + + + +// cookie for user, formtted with userID +static char const * const HTTP_200_FORMAT = "HTTP/1.1 200 OK\r\n\ +Content-Length: %ld\r\n\ +Content-Type: text/html\r\n\ +Set-Cookie: cookie_id= %d\r\n\r\n"; + + + + + +static char const * const HTTP_400 = "HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\n\r\n"; +static int const HTTP_400_LENGTH = 47; +static char const * const HTTP_404 = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n"; +static int const HTTP_404_LENGTH = 45; + + + +typedef enum +{ + GET, + POST, + UNKNOWN +} METHOD; + + + +// struct User +struct User { + int userID; + char* username; + char** keywords; + int isOnline; // Online=1, OffLine=0 + int stage; + int n_word; +}; + + +// malloc a newUser +struct User* newUser() { + struct User* newUser = malloc(sizeof (struct User)); + newUser->userID = 0; + //newUser->username = malloc(MAX_BUFF*sizeof(char)); + //newUser->keywords = NULL; + newUser->keywords =malloc(MAX_BUFF*sizeof(char*)); + for (int i = 0; i < MAX_BUFF; i++) + { + newUser->keywords[i] = NULL; + } + newUser->isOnline = 0; + newUser->stage = 0; + newUser->n_word = 0; + return newUser; +} + +void clear_user_keyword(struct User* user){ + user->stage=0; + user->isOnline=0; + user->n_word=0; + for (int i = 0; i < MAX_BUFF; i++) + { + user->keywords[i] = NULL; + } +} + +int find_cookie(char* buff) +{ + char* cookie_id=strstr(buff, "cookie_id="); + char* temp; + if(cookie_id == NULL) + { + return 0; + } + else + { + temp = malloc(sizeof(char)*strlen(cookie_id)+1); + strcpy(temp, cookie_id); + temp+=10; + } + printf("find_cookie in buff %s\n", cookie_id); + //int cookie_length = strlen(username); + temp[strlen(temp)-3]='\0'; + printf("find_cookie in buff %s\n", cookie_id); + + + return atoi(temp); +} + + +struct User* find_curr(struct User* user_arr[], char* buff) +{ + int cookie_id = find_cookie(buff); + + printf("the kmimimji%d %d\n", cookie_id,user_arr[0]->userID); + if(cookie_id==0){ + + struct User* curr_user = newUser(); + + + + if ((cookie_id!=1||cookie_id!=2)&& user_arr[0]->userID!=1) + { + curr_user->userID = 1; + user_arr[0]= curr_user; + } + else if((cookie_id!=1||cookie_id!=2)&& user_arr[1]->userID!=2){ + curr_user->userID = 2; + user_arr[1]= curr_user; + } + cookie_id=curr_user->userID; + printf(" func curr: cookie_id is %d\n%d\n\n\n", cookie_id,curr_user->userID); + } + + for (int i=0; i<2; i++) { + if (user_arr[i]->userID == cookie_id) + { + printf("existing curr user %d , with cookie_id %d", i,cookie_id); + return user_arr[i]; + + } + } + +} + +struct User* the_other_user(struct User* curr_user, struct User* user_arr[]){ + for(int i=0; i<2; i++){ + if (user_arr[i]!=curr_user){ + return user_arr[i]; + } + } +} + + +bool match(char* w1, char** w2, int n_word){ + for (int i=0; i<n_word; i++){ + if (w2[i]==w1){ + return true; + } + } + return false; +} + + +void simple_load_html(char* html, int sockfd, char* buff, int n, struct User* curr_user){ + struct stat st; + stat(html, &st); + n = sprintf(buff, HTTP_200_FORMAT, st.st_size+6,curr_user->userID); + if (write(sockfd, buff, n) < 0) + { + perror("write"); + return ; + } + int filefd = open(html, O_RDONLY); + do + { + n = sendfile(sockfd, filefd, NULL, 2048); + } + while (n > 0); + if (n < 0) + { + perror("sendfile"); + close(filefd); + return ; + } + close(filefd); +} + + /* adds the new word in the html (between the <body> */ +void plug_in_html(char* newword, char* old_buffer, char* new_buffer){ + + // slice the html string into 2 parts + char start[MAX_BUFF]; + char* end = strstr(old_buffer, "</body>"); + + // front part + strncpy(start, old_buffer, strlen(old_buffer)-strlen(end)); + start[strlen(start)] = '\0'; + + // combine + strcpy(new_buffer, start); + strcat(new_buffer, newword); + strcat(new_buffer, end); + + new_buffer[strlen(new_buffer)] = '\0'; +} + + + +void edit_load_html(char* html, int sockfd, char* buff, char* newword,struct User* curr_user){ + + // get the size of the file + struct stat st; + stat(html, &st); + + // increase file size to accommodate the new guess + int added_length= strlen(newword); + long size = st.st_size + added_length; + int n = sprintf(buff, HTTP_200_FORMAT, size+6, curr_user->userID); + // send the header first + if (write(sockfd, buff, n) < 0) + { + perror("write"); + return; + } + // read the content of the HTML file + int filefd = open(html, O_RDONLY); + n = read(filefd, buff, st.st_size); + if (n < 0) + { + perror("read"); + close(filefd); + return; + } + close(filefd); + + // makes new buffer, copies the username into it + char* new_buffer = (char *) malloc(sizeof(MAX_BUFF)); + plug_in_html(newword, buff, new_buffer); + + if (write(sockfd, new_buffer, size) < 0) + { + perror("write"); + return; + } + free(new_buffer); +} + +void record_keyword(struct User* curr_user, char *new_guess){ + for (int i=0; i<=curr_user->n_word; i++){ + if(curr_user->keywords[curr_user->n_word]==NULL){ + curr_user->keywords[curr_user->n_word] = malloc((1 + strlen(new_guess)) * sizeof(char*)); + strcpy(curr_user->keywords[curr_user->n_word],new_guess); + curr_user->n_word++; + break; + } + } +} + +static bool handle_http_request(int sockfd, struct User* user_arr[]) +{ + // try to read the request + char buff[2049]; + int n = read(sockfd, buff, 2049); + if (n <= 0) + { + if (n < 0) + perror("read"); + else + printf("socket %d close the connection\n", sockfd); + return false; + } + + // terminate the string + buff[n] = 0; + + char * curr = buff; + + // parse the method + METHOD method = UNKNOWN; + if (strncmp(curr, "GET ", 4) == 0) + { + curr += 4; + method = GET; + } + else if (strncmp(curr, "POST ", 5) == 0) + { + curr += 5; + method = POST; + } + else if (write(sockfd, HTTP_400, HTTP_400_LENGTH) < 0) + { + perror("write"); + return false; + } + + printf("buff1: \n"); + printf("%s\n",buff); + + struct User* curr_user=find_curr(user_arr,buff); + + // sanitise the URI + while (*curr == '.' || *curr == '/') + ++curr; + + printf("stage%d\n",curr_user->stage ); + // assume the only valid request URI is "/" but it can be modified to accept more files + if (*curr == ' ' || *curr == '?') + { + if (method == GET) + { + if (curr_user->isOnline==0) + { + simple_load_html("1_intro.html",sockfd,buff,n,curr_user); + + } + else if (curr_user->isOnline==1){ + simple_load_html("3_first_turn.html",sockfd,buff,n,curr_user); + curr_user->stage = 1; + } + else if (curr_user->stage==2){ + simple_load_html("3_first_turn.html",sockfd,buff,n,curr_user); + curr_user->stage = 1; + if (the_other_user(curr_user, user_arr)->stage==2){ + the_other_user(curr_user, user_arr)->stage==4; + } + } + } + else if (method == POST){ + + if(strstr(buff, "quit=Quit") != NULL) + { + + simple_load_html("7_gameover.html",sockfd,buff,n,curr_user); + curr_user->stage=3; + } + else if(curr_user->isOnline == 0) + { + + } + + } + + + + + + + + + + else + // never used, just for completeness + fprintf(stderr, "no other methods supported"); + } + // send 404 + else if (write(sockfd, HTTP_404, HTTP_404_LENGTH) < 0) + { + perror("write"); + return false; + } + + return true; +} + +int main(int argc, char * argv[]) +{ + if (argc < 3) + { + fprintf(stderr, "usage: %s ip port\n", argv[0]); + return 0; + } + + // create TCP socket which only accept IPv4 + int sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) + { + perror("socket"); + exit(EXIT_FAILURE); + } + + // reuse the socket if possible + int const reuse = 1; + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)) < 0) + { + perror("setsockopt"); + exit(EXIT_FAILURE); + } + + // create and initialise address we will listen on + struct sockaddr_in serv_addr; + bzero(&serv_addr, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + // if ip parameter is not specified + serv_addr.sin_addr.s_addr = inet_addr(argv[1]); + serv_addr.sin_port = htons(atoi(argv[2])); + + // bind address to socket + if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) + { + perror("bind"); + exit(EXIT_FAILURE); + } + + // listen on the socket + listen(sockfd, 5); + + // initialise an active file descriptors set + fd_set masterfds; + FD_ZERO(&masterfds); + FD_SET(sockfd, &masterfds); + // record the maximum socket number + int maxfd = sockfd; + + //global variable for 2 users + struct User* user_arr[2]; + + + + while (1) + { + // monitor file descriptors + fd_set readfds = masterfds; + if (select(FD_SETSIZE, &readfds, NULL, NULL, NULL) < 0) + { + perror("select"); + exit(EXIT_FAILURE); + } + + // loop all possible descriptor + for (int i = 0; i <= maxfd; ++i) + // determine if the current file descriptor is active + if (FD_ISSET(i, &readfds)) + { + // create new socket if there is new incoming connection request + if (i == sockfd) + { + struct sockaddr_in cliaddr; + socklen_t clilen = sizeof(cliaddr); + int newsockfd = accept(sockfd, (struct sockaddr *)&cliaddr, &clilen); + if (newsockfd < 0) + perror("accept"); + else + { + // add the socket to the set + FD_SET(newsockfd, &masterfds); + // update the maximum tracker + if (newsockfd > maxfd) + maxfd = newsockfd; + // print out the IP and the socket number + char ip[INET_ADDRSTRLEN]; + printf( + "new connection from %s on socket %d\n", + // convert to human readable string + inet_ntop(cliaddr.sin_family, &cliaddr.sin_addr, ip, INET_ADDRSTRLEN), + newsockfd + ); + } + } + // a request is sent from the client + else if (!handle_http_request(i, user_arr)) + { + close(i); + FD_CLR(i, &masterfds); + } + } + } + + return 0; +} + + diff --git a/new.c b/new.c new file mode 100644 index 0000000000000000000000000000000000000000..73d2f73742babccdad1da15bc2b8182668a88aea --- /dev/null +++ b/new.c @@ -0,0 +1,535 @@ +/* +** http-server.c +*/ + +#include <errno.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <arpa/inet.h> +#include <fcntl.h> +#include <netdb.h> +#include <netinet/in.h> +#include <strings.h> +#include <sys/select.h> +#include <sys/sendfile.h> + +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + + +#define MAX_BUFF 2049 + + + +// cookie for user, formtted with userID +static char const * const HTTP_200_FORMAT = "HTTP/1.1 200 OK\r\n\ +Content-Length: %ld\r\n\ +Content-Type: text/html\r\n\ +Set-Cookie: cookie_id= %d\r\n\r\n"; + + + + + +static char const * const HTTP_400 = "HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\n\r\n"; +static int const HTTP_400_LENGTH = 47; +static char const * const HTTP_404 = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n"; +static int const HTTP_404_LENGTH = 45; + + + +typedef enum +{ + GET, + POST, + UNKNOWN +} METHOD; + + + +// struct User +struct User { + int userID; + char* username; + char** keywords; + int isOnline; // Online=1, OffLine=0 + int stage; + int n_word; +}; + + +// malloc a newUser +struct User* newUser() { + struct User* newUser = malloc(sizeof (struct User)); + newUser->userID = 0; + //newUser->username = malloc(MAX_BUFF*sizeof(char)); + //newUser->keywords = NULL; + newUser->keywords =malloc(MAX_BUFF*sizeof(char*)); + for (int i = 0; i < MAX_BUFF; i++) + { + newUser->keywords[i] = NULL; + } + newUser->isOnline = 0; + newUser->stage = 0; + newUser->n_word = 0; + return newUser; +} + +void clear_user_keyword(struct User* user){ + user->stage=0; + user->isOnline=0; + user->n_word=0; + for (int i = 0; i < MAX_BUFF; i++) + { + user->keywords[i] = NULL; + } +} + +int find_cookie(char* buff) +{ + char* cookie_id=strstr(buff, "cookie_id="); + char* temp; + if(cookie_id == NULL) + { + return 0; + } + else + { + temp = malloc(sizeof(char)*strlen(cookie_id)+1); + strcpy(temp, cookie_id); + temp+=10; + } + printf("find_cookie in buff %s\n", cookie_id); + //int cookie_length = strlen(username); + temp[strlen(temp)-3]='\0'; + printf("find_cookie in buff %s\n", cookie_id); + + + return atoi(temp); +} + + +struct User* find_curr(struct User* user_arr[], char* buff) +{ + int cookie_id = find_cookie(buff); + + printf("the kmimimji%d %d\n", cookie_id,user_arr[0]->userID); + if(cookie_id==0){ + + struct User* curr_user = newUser(); + + + + if ((cookie_id!=1||cookie_id!=2)&& user_arr[0]->userID!=1) + { + curr_user->userID = 1; + user_arr[0]= curr_user; + } + else if((cookie_id!=1||cookie_id!=2)&& user_arr[1]->userID!=2){ + curr_user->userID = 2; + user_arr[1]= curr_user; + } + cookie_id=curr_user->userID; + printf(" func curr: cookie_id is %d\n%d\n\n\n", cookie_id,curr_user->userID); + } + + for (int i=0; i<2; i++) { + if (user_arr[i]->userID == cookie_id) + { + printf("existing curr user %d , with cookie_id %d", i,cookie_id); + return user_arr[i]; + + } + } + +} + +struct User* the_other_user(struct User* curr_user, struct User* user_arr[]){ + for(int i=0; i<2; i++){ + if (user_arr[i]!=curr_user){ + return user_arr[i]; + } + } +} + + +bool match(char* w1, char** w2, int n_word){ + for (int i=0; i<n_word; i++){ + if (w2[i]==w1){ + return true; + } + } + return false; +} + + +void simple_load_html(char* html, int sockfd, char* buff, int n, struct User* curr_user){ + struct stat st; + stat(html, &st); + n = sprintf(buff, HTTP_200_FORMAT, st.st_size+6,curr_user->userID); + if (write(sockfd, buff, n) < 0) + { + perror("write"); + return ; + } + int filefd = open(html, O_RDONLY); + do + { + n = sendfile(sockfd, filefd, NULL, 2048); + } + while (n > 0); + if (n < 0) + { + perror("sendfile"); + close(filefd); + return ; + } + close(filefd); +} + + /* adds the new word in the html (between the <body> */ +void plug_in_html(char* newword, char* old_buffer, char* new_buffer){ + + // slice the html string into 2 parts + char start[MAX_BUFF]; + char* end = strstr(old_buffer, "</body>"); + + // front part + strncpy(start, old_buffer, strlen(old_buffer)-strlen(end)); + start[strlen(start)] = '\0'; + + // combine + strcpy(new_buffer, start); + strcat(new_buffer, newword); + strcat(new_buffer, end); + + new_buffer[strlen(new_buffer)] = '\0'; +} + + + +void edit_load_html(char* html, int sockfd, char* buff, char* newword,struct User* curr_user){ + + // get the size of the file + struct stat st; + stat(html, &st); + + // increase file size to accommodate the new guess + int added_length= strlen(newword); + long size = st.st_size + added_length; + int n = sprintf(buff, HTTP_200_FORMAT, size+6, curr_user->userID); + // send the header first + if (write(sockfd, buff, n) < 0) + { + perror("write"); + return; + } + // read the content of the HTML file + int filefd = open(html, O_RDONLY); + n = read(filefd, buff, st.st_size); + if (n < 0) + { + perror("read"); + close(filefd); + return; + } + close(filefd); + + // makes new buffer, copies the username into it + char* new_buffer = (char *) malloc(sizeof(MAX_BUFF)); + plug_in_html(newword, buff, new_buffer); + + if (write(sockfd, new_buffer, size) < 0) + { + perror("write"); + return; + } + free(new_buffer); +} + +void record_keyword(struct User* curr_user, char *new_guess){ + for (int i=0; i<=curr_user->n_word; i++){ + if(curr_user->keywords[curr_user->n_word]==NULL){ + curr_user->keywords[curr_user->n_word] = malloc((1 + strlen(new_guess)) * sizeof(char*)); + strcpy(curr_user->keywords[curr_user->n_word],new_guess); + curr_user->n_word++; + break; + } + } +} + +static bool handle_http_request(int sockfd, struct User* user_arr[]) +{ + // try to read the request + char buff[2049]; + int n = read(sockfd, buff, 2049); + if (n <= 0) + { + if (n < 0) + perror("read"); + else + printf("socket %d close the connection\n", sockfd); + return false; + } + + // terminate the string + buff[n] = 0; + + char * curr = buff; + + // parse the method + METHOD method = UNKNOWN; + if (strncmp(curr, "GET ", 4) == 0) + { + curr += 4; + method = GET; + } + else if (strncmp(curr, "POST ", 5) == 0) + { + curr += 5; + method = POST; + } + else if (write(sockfd, HTTP_400, HTTP_400_LENGTH) < 0) + { + perror("write"); + return false; + } + + printf("buff1: \n"); + printf("%s\n",buff); + + struct User* curr_user=find_curr(user_arr,buff); + + // sanitise the URI + while (*curr == '.' || *curr == '/') + ++curr; + + printf("stage%d\n",curr_user->stage ); + // assume the only valid request URI is "/" but it can be modified to accept more files + if (*curr == ' ' || *curr == '?') + + //Stage1: when user name is not registed + if (curr_user->stage==0){ + if (method==GET) + { + printf("curr_user->username%s == %d\n", curr_user->username,curr_user->username==NULL); + simple_load_html("1_intro.html",sockfd,buff,n,curr_user); + } + + else if (method == POST) + { + printf("curr_user->username%s == %d\n", curr_user->username,curr_user->username==NULL); + // locate the username, it is safe to do so in this sample code, but usually the result is expected to be + // copied to another buffer using strcpy or strncpy to ensure that it will not be overwritten. + char * user = strstr(buff, "user=") + 5; + char username[MAX_BUFF]; + strcpy(username, "<br>"); + strcat(username, user); + username[strlen(username)] = '\0'; + edit_load_html("2_start.html", sockfd,buff,username,curr_user); + printf("buffer %s\n",buff ); + curr_user->stage=1; + } + } + + + //Stage 1: start the game + else if(curr_user->stage==1) + { + + // quit: user not online + if(strstr(buff, "quit=Quit") != NULL) + { curr_user->isOnline=0; + simple_load_html("7_gameover.html",sockfd,buff,n,curr_user); + curr_user->stage=3; + + } + // start is the only GET mathod for ther stage 1 + else if (method == GET) + { curr_user->isOnline=1; + simple_load_html("3_first_turn.html",sockfd,buff,n,curr_user); + curr_user->stage =2; + curr_user->isOnline=1; + } + } + + + // Stage 2: in the process of guessing + else if (curr_user->stage ==2){ + + char * new_guess = strstr(buff, "keyword=") + 8; + + if(strstr(buff, "quit=Quit") != NULL) + { curr_user->isOnline=0; + simple_load_html("7_gameover.html",sockfd,buff,n,curr_user); + clear_user_keyword(curr_user); + } + + else if (the_other_user(curr_user, user_arr)->stage==3){ + simple_load_html("7_gameover.html",sockfd,buff,n,curr_user); + clear_user_keyword(curr_user); + } + + else if(the_other_user(curr_user, user_arr)->isOnline==0){ + simple_load_html("5_discarded.html",sockfd,buff,n,curr_user); + clear_user_keyword(curr_user); + } + + + else if(new_guess!=NULL){ + if(match(new_guess, the_other_user(curr_user, user_arr)->keywords, the_other_user(curr_user, user_arr)->n_word)) + { + simple_load_html("6_endgame.html",sockfd,buff,n,curr_user); + clear_user_keyword(curr_user); + } + else{ + curr_user->stage =2; + printf("curr_user->n_word%d\n",curr_user->n_word ); + // remember new guess + record_keyword(curr_user, new_guess); + // display new guess + char guess[MAX_BUFF]; + strcpy(guess,"<br>"); + if (curr_user->n_word==1){ + strcat(guess, new_guess); + guess[strlen(new_guess)]='\0'; + }else + { + for (int i = 0; i < curr_user->n_word; i++) + { + strcat(guess, curr_user->keywords[i]); + strcat(guess,"<br>"); + } + } + + edit_load_html("4_accepted.html", sockfd,buff,guess,curr_user); + } + } + + + + } + else + // never used, just for completeness + fprintf(stderr, "no other methods supported"); + // send 404 + else if (write(sockfd, HTTP_404, HTTP_404_LENGTH) < 0) + { + perror("write"); + return false; + } + + return true; +} + +int main(int argc, char * argv[]) +{ + if (argc < 3) + { + fprintf(stderr, "usage: %s ip port\n", argv[0]); + return 0; + } + + // create TCP socket which only accept IPv4 + int sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) + { + perror("socket"); + exit(EXIT_FAILURE); + } + + // reuse the socket if possible + int const reuse = 1; + if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)) < 0) + { + perror("setsockopt"); + exit(EXIT_FAILURE); + } + + // create and initialise address we will listen on + struct sockaddr_in serv_addr; + bzero(&serv_addr, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + // if ip parameter is not specified + serv_addr.sin_addr.s_addr = inet_addr(argv[1]); + serv_addr.sin_port = htons(atoi(argv[2])); + + // bind address to socket + if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) + { + perror("bind"); + exit(EXIT_FAILURE); + } + + // listen on the socket + listen(sockfd, 5); + + // initialise an active file descriptors set + fd_set masterfds; + FD_ZERO(&masterfds); + FD_SET(sockfd, &masterfds); + // record the maximum socket number + int maxfd = sockfd; + + //global variable for 2 users + struct User* user_arr[2]; + + + + while (1) + { + // monitor file descriptors + fd_set readfds = masterfds; + if (select(FD_SETSIZE, &readfds, NULL, NULL, NULL) < 0) + { + perror("select"); + exit(EXIT_FAILURE); + } + + // loop all possible descriptor + for (int i = 0; i <= maxfd; ++i) + // determine if the current file descriptor is active + if (FD_ISSET(i, &readfds)) + { + // create new socket if there is new incoming connection request + if (i == sockfd) + { + struct sockaddr_in cliaddr; + socklen_t clilen = sizeof(cliaddr); + int newsockfd = accept(sockfd, (struct sockaddr *)&cliaddr, &clilen); + if (newsockfd < 0) + perror("accept"); + else + { + // add the socket to the set + FD_SET(newsockfd, &masterfds); + // update the maximum tracker + if (newsockfd > maxfd) + maxfd = newsockfd; + // print out the IP and the socket number + char ip[INET_ADDRSTRLEN]; + printf( + "new connection from %s on socket %d\n", + // convert to human readable string + inet_ntop(cliaddr.sin_family, &cliaddr.sin_addr, ip, INET_ADDRSTRLEN), + newsockfd + ); + } + } + // a request is sent from the client + else if (!handle_http_request(i, user_arr)) + { + close(i); + FD_CLR(i, &masterfds); + } + } + } + + return 0; +} + +