Skip to content
Snippets Groups Projects
Commit a9beaa09 authored by Alexander Cock's avatar Alexander Cock
Browse files

Initialise GIT repository

parent be1c94f8
Branches
No related tags found
No related merge requests found
Makefile 0 → 100644
CC=gcc
CPPFLAGS=-Wall -Werror -O3
SRC=image_tagger.c
TARGET=image_tagger
all: $(SRC)
$(CC) -o $(TARGET) $(SRC) $(CPPFLAGS)
clean:
rm -f $(TARGET) *.o
\ No newline at end of file
/*
* image_tagger.c
* source code from Lab 5/6 of COMP30023
*/
#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/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
// constants
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;
//static char * PLAYER_1_NAME;
//static char * PLAYER_2_NAME;
//static int PLAYER_1_GAME_STATE = 0;
//static int PLAYER_2_GAME_STATE = 0;
static char* KEYWORD_LIST_P1[100];
static char* KEYWORD_LIST_P2[100];
static int NUM_KEYWORD_P1 = 0;
static int NUM_KEYWORD_P2 = 0;
// represents the types of method
typedef enum
{
GET,
POST,
UNKNOWN
} METHOD;
static char* getURL(char* curr) {
char* url;
if (strncmp(curr, "1_intro.html ", 13) == 0 || strncmp(curr, " HTTP/1.1", 9) == 0)
{
url = "1_intro.html";
} else if(strncmp(curr, "2_start.html ", 13) == 0)
{
url = "2_start.html";
} else if(strncmp(curr, "3_first_turn.html ", 18) == 0 || strncmp(curr, "?start=Start ", 13) == 0)
{
url = "3_first_turn.html";
} else if(strncmp(curr, "4_accepted.html ", 16) == 0)
{
url = "4_accepted.html";
} else if(strncmp(curr, "5_discarded.html ", 17) == 0)
{
url = "5_discarded.html";
} else if(strncmp(curr, "6_endgame.html ", 15) == 0)
{
url = "6_endgame.html";
} else if(strncmp(curr, "7_gameover.html ", 16) == 0)
{
url = "7_gameover.html";
} else {
url = " ";
}
return url;
}
static bool addKeyword(char * keyword, int playerNum) {
int i = 0;
bool match = false;
if(playerNum == 1) {
while(KEYWORD_LIST_P2[i] != NULL) {
if((strcmp(KEYWORD_LIST_P2[i], keyword)) == 0) {
match = true;
}
i++;
}
KEYWORD_LIST_P1[NUM_KEYWORD_P1] = keyword;
NUM_KEYWORD_P1++;
} else {
while(KEYWORD_LIST_P1[i] != NULL) {
if((strcmp(KEYWORD_LIST_P1[i], keyword)) == 0) {
match = true;
}
i++;
}
KEYWORD_LIST_P2[NUM_KEYWORD_P2] = keyword;
NUM_KEYWORD_P2++;
}
return match;
}
static bool getRequest(int sockfd, char* buff, char* url, int n) {
// get the size of the file
struct stat st;
stat(url, &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(url, 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 postRequest(int sockfd, char* buff, char* url, int n) {
char * file;
char * post = "hello";
if(strcmp(url,"1_intro.html")) {
file = "2_start.html";
} else if(strcmp(url,"2_start.html")) {
//file = "7_gameover.html";
} else if(strcmp(url,"3_first_turn.html")) {
if(addKeyword(post,1)) {
file = "6_endgame.html";
} else {
file = "4_accepted.html";
}
}
struct stat st;
stat(file, &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(file, 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)
{
// try to read the request
char buff[2049];
char * url;
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;
printf("%s /n", buff);
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 != '\0')
{
url = getURL(curr);
if(strcmp(url," ") == 0) {
perror("read");
return false;
}
if (method == GET)
{
if(getRequest(sockfd,buff,url,n) == false) {
return false;
}
}
else if (method == POST)
{
if(postRequest(sockfd,buff,url,n) == false) {
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;
}
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;
char str[INET_ADDRSTRLEN];
printf("image_tagger server is now running at IP: %s on port %d\n", inet_ntop(AF_INET, &serv_addr.sin_addr, str, INET_ADDRSTRLEN), ntohs(serv_addr.sin_port));
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))
{
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