#ifndef _REENTRANT #define _REENTRANT #endif #include #include #include #include #include #include #include #include #include #include #include #include "util.h" //Global socket int sockfd, new_socket; /********************************************** * init - port is the number of the port you want the server to be started on - initializes the connection acception/handling system - YOU MUST CALL THIS EXACTLY ONCE (not once per thread, but exactly one time, in the main thread of your program) BEFORE USING ANY OF THE FUNCTIONS BELOW - if init encounters any errors, it will call exit(). ************************************************/ void init(int port) { if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { perror("Cannot create socket"); exit(EXIT_FAILURE); } //Socket describer struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(port); //Allow port to be released int enable = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&enable, sizeof(int)) == -1) { perror("Cannot set socket option"); exit(EXIT_FAILURE); } //Bind socket and open the port if (bind(sockfd, (struct sockaddr*) &addr, sizeof(addr)) == -1) { perror("Cannot bind socket"); exit(EXIT_FAILURE); } //Enable listen if (listen(sockfd, 20) == -1) { perror("Cannot set listen queue"); exit(EXIT_FAILURE); } } /********************************************** * accept_connection - takes no parameters - returns a file descriptor for further request processing. DO NOT use the file descriptor on your own -- use get_request() instead. - if the return value is negative, the request should be ignored. ***********************************************/ int accept_connection(void) { struct sockaddr_in address; int addrlen = sizeof(address); if ((new_socket = accept(sockfd, (struct sockaddr *)&address, (socklen_t*)&addrlen))<0) { perror("Accept"); return -1; } return(new_socket); } /********************************************** * get_request - parameters: - fd is the file descriptor obtained by accept_connection() from where you wish to get a request - filename is the location of a character buffer in which this function should store the requested filename. (Buffer should be of size 1024 bytes.) - returns 0 on success, nonzero on failure. You must account for failures because some connections might send faulty requests. This is a recoverable error - you must not exit inside the thread that called get_request. After an error, you must NOT use a return_request or return_error function for that specific 'connection'. ************************************************/ int get_request(int fd, char *filename) { char buffer[2048] = "\0"; char get[100], http[100]; read(fd, buffer, 2048); if(sscanf(buffer, "%s %s %s", get, filename, http) < 2) { // Read HTTP Get request and parse close(fd); return -1; } else if (strcmp(get, "GET")) { close(fd); return -2; } else if (strlen(filename) > 1023) { close(fd); return -3; } for (int i=0; i