Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <errno.h>
- #include <string.h>
- #include <netdb.h>
- #include <signal.h>
- #include <assert.h>
- #include <time.h>
- #include <sys/types.h>
- #include <netinet/in.h>
- #include <sys/socket.h>
- #include <inttypes.h>
- #include <arpa/inet.h>
- void usage(char *fileName)
- {
- fprintf(stderr, "%s [-p PORT] [-i INDEX] DOC_ROOT\n", fileName);
- exit(EXIT_FAILURE);
- }
- int serverSocket = 0;
- int clientSocket = 0;
- void handleSignal(int sig)
- {
- if (serverSocket > 0) {
- shutdown(serverSocket, SHUT_RDWR);
- close(serverSocket);
- }
- if (clientSocket > 0) {
- shutdown(clientSocket, SHUT_RDWR);
- close(clientSocket);
- }
- exit(EXIT_SUCCESS);
- }
- /**
- * Method that checks if the first string starts with another string
- * @brief compare string beginnng with others tring
- * @param a,b - two strings
- */
- int startsWith(const char *a, const char *b)
- {
- if(strncmp(a, b, strlen(b)) == 0) return 1;
- return 0;
- }
- int main(int argc, char *argv[]) {
- if (argc < 2) usage(argv[0]);
- char * port = "8080";
- char * file = "index.html";
- int c = 0;
- while ((c = getopt(argc, argv, ":p:i:")) != -1)
- {
- switch (c)
- {
- case 'p':
- port = strdup(optarg);
- break;
- case 'i':
- file = strdup(optarg);
- break;
- case '?':
- usage(argv[0]);
- default:
- assert(0);
- exit(EXIT_FAILURE);
- }
- }
- char * root;
- // check root parameter
- if (optind >= argc) {
- usage(argv[0]);
- }
- else {
- root = argv[optind];
- }
- //-------------------------------------------------------- Create Server Socket --------------------------------------------------
- char* ptr = NULL;
- unsigned short int portValue = (unsigned short int)strtol(port, &ptr, 10);
- if (!ptr)
- {
- fprintf(stderr, "Invalid port %s\n", port);
- exit(EXIT_FAILURE);
- }
- // create
- serverSocket = socket(AF_INET, SOCK_STREAM, 0);
- if (serverSocket == 0) {
- fprintf(stderr, "Bad socket: %s\n", strerror(errno));
- exit(EXIT_FAILURE);
- }
- // set server port
- struct sockaddr_in addr;
- memset(&addr, 0, sizeof addr);
- addr.sin_family = AF_INET;
- addr.sin_port = htons(portValue);
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- //bind
- if (bind(serverSocket, (struct sockaddr *)&addr, sizeof(struct sockaddr))== -1) {
- fprintf(stderr, "Error when binding %s\n", strerror(errno));
- close(serverSocket);
- exit(EXIT_FAILURE);
- }
- // listen
- if (listen(serverSocket, SOMAXCONN) == -1) {
- fprintf(stderr, "Error when listening %s\n", strerror(errno));
- close(serverSocket);
- exit(EXIT_FAILURE);
- }
- // enable signals
- signal(SIGINT, handleSignal);
- signal(SIGTERM, handleSignal);
- //--------------------------------------------------------------------------------------------------------------------------------
- //-------------------------------------------------------- Accept incoming client connections ------------------------------------
- while (1)
- {
- clientSocket = accept(serverSocket, NULL, NULL);
- if (clientSocket < 0) {
- fprintf(stderr, "Error when accepting client.");
- break;
- }
- char request[1023];
- ssize_t received = recv(clientSocket, request, 1023, 0);
- if (received <= 0) {
- shutdown(clientSocket, SHUT_RDWR);
- close(clientSocket);
- continue;
- }
- //-------------------------------------------------------------------------------------------------- Handle request
- // parse first line
- char *ptr = strstr(request, " HTTP/1.1\r\n");
- // if invalid HTTP header, reply 400 error
- if (!ptr) {
- char errorResponse[1023];
- size_t lenghtError = sprintf(errorResponse, "HTTP/1.1 %d %s\r\nConnection: close\r\n\r\n", 400, "Bad Request");
- send(clientSocket, errorResponse, lenghtError, 0);
- }
- // if unsupported HTTP command except GET, reply 501 error
- else if (strstr(request, "GET ") != request) {
- char errorResponse[1023];
- size_t lenghtError = sprintf(errorResponse, "HTTP/1.1 %d %s\r\nConnection: close\r\n\r\n", 501, "Not implemented");
- send(clientSocket, errorResponse, lenghtError, 0);
- }
- // parse target path from the first line
- else
- {
- *ptr = '\0'; // erase end
- char *pathname = strdup(root);
- strcat(pathname, "/");
- if (strcmp(request + 4, "/") == 0) strcat(pathname, file); // if "/" is given, set default file
- else strcat(pathname, request + 5); // otherwise, set given path
- // try to open file
- FILE *fp = fopen(pathname, "r");
- // if failed, reply 404 error
- if (!fp) {
- char errorResponse[1023];
- size_t lenghtError = sprintf(errorResponse, "HTTP/1.1 %d %s\r\nConnection: close\r\n\r\n", 404, "Not found");
- send(clientSocket, errorResponse, lenghtError, 0);
- }
- else
- {
- // get current timestamp
- char timestamp[1023];
- time_t tmp = time(NULL);
- struct tm t = *localtime(&tmp);
- strftime(timestamp, sizeof(timestamp), "%a, %d %b %Y %T %z", &t);
- // get content length
- int content_length = 0;
- fseek(fp, 0L, SEEK_END);
- content_length = ftell(fp);
- fseek(fp, 0L, SEEK_SET);
- // send HTTP 200 reply
- char respond[1023];
- size_t size = sprintf(respond, "HTTP/1.1 200 OK\r\nDate: %s\r\nContent-Length: %d\r\nConnection: close\r\n\r\n", timestamp, content_length);
- send(clientSocket, respond, size, 0);
- if (content_length > 0) {
- char data[1023];
- ssize_t bytes = 0;
- do{
- // try to read all data from the file and send to the client
- bytes = fread(data, 1, 1023, fp);
- if (bytes > 0) send(clientSocket, data, bytes, 0);
- } while(bytes > 0);
- }
- //close file handle
- fclose(fp);
- }
- }
- //-------------------------------------------------------------------------------------------------- Handle request over------------------------------------
- shutdown(clientSocket, SHUT_RDWR);
- close(clientSocket);
- }
- //--------------------------------------------------------------------------------------------------------------------------------
- return EXIT_SUCCESS;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement