Skip to content
Snippets Groups Projects
Commit 5b7b782e authored by qifant's avatar qifant
Browse files

final work

parents
Branches master
No related tags found
No related merge requests found
Pipeline #1912 failed
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h2>Image Tagger Game</h2>
<img src="https://swift.rc.nectar.org.au/v1/AUTH_eab314456b624071ac5aecd721b977f0/comp30023-project/image-3.jpg" alt="HTML5 Icon" style="width:700px;height:400px;">
<p>Welcome to the image tagging game. Please enter your name below.</p>
<form method="POST">
Name: <input type="text" name="user" />
<input type="submit" class="button" />
</form>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h2>Image Tagger Game</h2>
<img src="https://swift.rc.nectar.org.au/v1/AUTH_eab314456b624071ac5aecd721b977f0/comp30023-project/image-3.jpg" alt="HTML5 Icon" style="width:700px;height:400px;">
<form method="GET">
<input type="submit" class="button" name="start" value="Start"/>
</form>
<form method="POST">
<input type="submit" class="button" name="quit" value="Quit"/>
</form>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h2>You are ready now!</h2>
<img src="https://swift.rc.nectar.org.au/v1/AUTH_eab314456b624071ac5aecd721b977f0/comp30023-project/image-2.jpg" alt="HTML5 Icon" style="width:700px;height:400px;">
<p>Rule: Try to guess the above image by typing a keyword which describes it:</p>
<form method="POST">
Keyword: <input type="text" name="keyword" />
<input type="submit" class="button" name="guess" value="Guess" />
</form>
<form method="POST">
<input type="submit" class="button" name="quit" value="Quit"/>
</form>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h2>Keyword Accepted! Keep trying more.</h2>
<img src="https://swift.rc.nectar.org.au/v1/AUTH_eab314456b624071ac5aecd721b977f0/comp30023-project/image-2.jpg" alt="HTML5 Icon" style="width:700px;height:400px;">
<p>Rule: Try to guess the above image by typing a keyword which describes it:</p>
<form method="POST">
Keyword: <input type="text" name="keyword" />
<input type="submit" class="button" name="guess" value="Guess" />
</form>
<form method="POST">
<input type="submit" class="button" name="quit" value="Quit"/>
</form>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h2>Keyword Discarded. The other player is not ready yet.</h2>
<img src="https://swift.rc.nectar.org.au/v1/AUTH_eab314456b624071ac5aecd721b977f0/comp30023-project/image-2.jpg" alt="HTML5 Icon" style="width:700px;height:400px;">
<p>Rule: Try to guess the above image by typing a keyword which describes it:</p>
<form method="POST">
Keyword: <input type="text" name="keyword" />
<input type="submit" class="button" name="guess" value="Guess" />
</form>
<form method="POST">
<input type="submit" class="button" name="quit" value="Quit"/>
</form>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h2>Thanks for playing. The game is completed.</h2>
<p>Would you like to play it again?</p>
<form method="GET">
<input type="submit" class="button" name="start" value="Start"/>
</form>
<form method="POST">
<input type="submit" class="button" name="quit" value="Quit"/>
</form>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h2>Game Over!</h2>
</body>
</html>
image_tagger: image_tagger.c
gcc -o image_tagger image_tagger.c
\ No newline at end of file
/*
** Qifan Tang 754831
** these are mostly copied from the http-server.c from sample code provided
** + sign means copied and - sign means modified code
** http-server.c
*/
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.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/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
//---------------------------------------------------------------
//function declaration
bool checkwords(int sockfd, char* word);
static bool sendpage(char* pagepath, char buff[], int sockfd, int n);
//---------------------------------------------------------------
// constants same as http-server.c
// i would modify the length to strlen so that it is more clear without the magic nubmers
static char const * const HTTP_200_FORMAT = "HTTP/1.1 200 OK\r\n\
Content-Type: text/html\r\n\
Content-Length: %ld\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;
//constants for the users
//---------------------------------------------------------------
int user1, user2;
char wordlist1[100][30], wordlist2[100][30];
int wl1size, wl2size;
bool rightflag;
bool quitflag;
//---------------------------------------------------------------
// represents the types of method same as http-server
typedef enum
{
GET,
POST,
UNKNOWN
} METHOD;
// this is used to reduce the repeated code of sending pages
static bool sendpage(char* pagepath, char buff[], int sockfd, int n)
{
// get the size of the file
struct stat st;
stat(pagepath, &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(pagepath, 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;
}
static bool handle_http_request(int sockfd)
{
//same as the http-server.c
// 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;
}
//---------------------------------------------------------------
if (user1 < 0 && user2 < 0)
{
rightflag = false;
quitflag = false;
}
//record the user by sockfd
else if (user1 < 0 && sockfd != user2)
{
user1 = sockfd;
}
else if (user2 < 0 && sockfd != user1)
{
user2 = sockfd;
}
//only accept two players at the moment
//---------------------------------------------------------------
// terminate the string same as http-server.c
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;
}
// sanitise the URI
while (*curr == '.' || *curr == '/')
++curr;
// assume the only valid request URI is "/" but it can be modified to accept more files
if (*curr == ' ')
if (method == GET)
{
if(!sendpage("1_intro.html", buff, sockfd, n))
{
return false;
}
}
else if (method == POST)
{
//-------------------------------------------------------------------
//if the user click quit
if(strstr(buff, "quit=") != NULL) {
if ( sockfd == user1) {
user1 = -1;
quitflag = true;
} else if ( sockfd == user2){
user2 = -1;
quitflag = true;
}
if(!sendpage("7_gameover.html", buff, sockfd, n))
{
return false;
}
}
//if the user enters the name same as the http-serve.c
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
// copied to another buffer using strcpy or strncpy to ensure that it will not be overwritten.
char * username = strstr(buff, "user=") + 5;
int username_length = strlen(username);
// the length needs to include the ", " before the username
long added_length = username_length + 9;
if(!sendpage("2_start.html", buff, sockfd, n))
{
return false;
}
// move the trailing part backward
// get the size of the file
struct stat st;
stat("2_start.html", &st);
// increase file size to accommodate the username
long size = st.st_size + added_length;
int p1, p2;
for (p1 = size - 1, p2 = p1 - added_length; p1 >= size - 25; --p1, --p2)
buff[p1] = buff[p2];
++p2;
// put the separator
buff[p2++] = ',';
buff[p2++] = ' ';
// copy the username
strncpy(buff + p2, username, username_length);
if (write(sockfd, buff, size) < 0)
{
perror("write");
return false;
}
}
}
else
// never used, just for completeness
fprintf(stderr, "no other methods supported");
else if (*curr == '?')
{
if (method == GET)
{
if(!sendpage("3_first_turn.html", buff, sockfd, n))
{
return false;
}
}
else if (method == POST)
{
//if quit
if(strstr(buff, "quit=") != NULL)
{
if ( sockfd == user1)
{
user1 = -1;
quitflag = true;
}
else if ( sockfd == user2)
{
user2 = -1;
quitflag = true;
}
if(!sendpage("7_gameover.html", buff, sockfd, n))
{
return false;
}
}
//if a word is given
else if (strstr(buff, "guess=") != NULL)
{
char * getword = strstr(buff, "keyword=") + 8;
//if the other user quit
if (quitflag)
{
if(!sendpage("7_gameover.html", buff, sockfd, n))
{
return false;
}
}
//if the other user guess the right word
if(rightflag)
{
if (sockfd == user1)
{
user1 = -1;
wl1size = 0;
} else if (sockfd == user2)
{
user2 = -1;
wl2size = 0;
}
if(!sendpage("6_endgame.html", buff, sockfd, n))
{
return false;
}
}
if ((user1 > 0) && (user2 > 0))
{
//pass the word to check
if (checkwords(sockfd, getword))
{
//reset everything
if (sockfd == user1) {
user1 = -1;
wl1size = 0;
} else if (sockfd == user2) {
user2 = -1;
wl2size = 0;
}
if(!sendpage("6_endgame.html", buff, sockfd, n))
{
return false;
}
}
else
{
if(!sendpage("4_accepted.html", buff, sockfd, n))
{
return false;
}
}
}
//if not enough users
else
{
if(!sendpage("5_discarded.html", buff, sockfd, n))
{
return false;
}
}
}
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;
}
//check if the words are repeated
bool checkwords(int sockfd, char* word) {
if (sockfd == user1)
{
for (int i = 0; i < wl2size; i++){
if (strcmp(word, wordlist2[i]) == 0) {
rightflag = true;
return true;
}
}
strcpy(wordlist1[wl1size], word);
wl1size++;
}
else if (sockfd == user2)
{
for (int i = 0; i < wl1size; i++)
{
if (strcmp(word, wordlist1[i]) == 0)
{
rightflag = true;
return true;
}
}
strcpy(wordlist2[wl2size], word);
wl2size++;
}
return false;
}
//mainly the same as the http-server.c
int main(int argc, char * argv[])
{
if (argc < 3)
{
fprintf(stderr, "usage: %s ip port\n", argv[0]);
return 0;
}
//initialise the constants
user1 = -1;
user2 = -1;
wl1size = 0;
wl2size = 0;
rightflag = false;
quitflag = false;
// 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;
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 is now running at IP: %s on port %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))
{
close(i);
FD_CLR(i, &masterfds);
}
}
}
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment