Advertisement
Guest User

Untitled

a guest
Nov 17th, 2019
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.09 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <errno.h>
  5. #include <string.h>
  6. #include <netdb.h>
  7. #include <signal.h>
  8. #include <assert.h>
  9. #include <time.h>
  10. #include <sys/types.h>
  11. #include <netinet/in.h>
  12. #include <sys/socket.h>
  13. #include <inttypes.h>
  14. #include <arpa/inet.h>
  15.  
  16. void usage(char *fileName)
  17. {
  18.     fprintf(stderr, "%s [-p PORT] [-i INDEX] DOC_ROOT\n", fileName);
  19.     exit(EXIT_FAILURE);
  20. }
  21.  
  22.  
  23. int serverSocket = 0;
  24. int clientSocket = 0;
  25.  
  26. void handleSignal(int sig)
  27. {
  28.     if (serverSocket > 0) {
  29.         shutdown(serverSocket, SHUT_RDWR);
  30.         close(serverSocket);
  31.     }
  32.     if (clientSocket > 0) {
  33.         shutdown(clientSocket, SHUT_RDWR);
  34.         close(clientSocket);
  35.     }
  36.     exit(EXIT_SUCCESS);
  37. }
  38.  
  39. /**
  40.  * Method that checks if the first string starts with another string
  41.  * @brief compare string beginnng with others tring
  42.  * @param a,b - two strings
  43.  */
  44. int startsWith(const char *a, const char *b)
  45. {
  46.    if(strncmp(a, b, strlen(b)) == 0) return 1;
  47.    return 0;
  48. }
  49.  
  50. int main(int argc, char *argv[]) {
  51.    
  52.     if (argc < 2) usage(argv[0]);
  53.    
  54.     char * port = "8080";
  55.     char * file = "index.html";
  56.    
  57.     int c = 0;
  58.     while ((c = getopt(argc, argv, ":p:i:")) != -1)
  59.     {
  60.         switch (c)
  61.         {
  62.             case 'p':
  63.                 port = strdup(optarg);
  64.                 break;
  65.             case 'i':
  66.                 file = strdup(optarg);
  67.                 break;
  68.             case '?':
  69.                 usage(argv[0]);
  70.             default:
  71.                 assert(0);
  72.                 exit(EXIT_FAILURE);    
  73.         }
  74.     }
  75.    
  76.     char * root;
  77.    
  78.     // check root parameter
  79.     if (optind >= argc) {
  80.         usage(argv[0]);
  81.     }
  82.     else {
  83.         root = argv[optind];
  84.     }
  85.    
  86.     //-------------------------------------------------------- Create Server Socket --------------------------------------------------
  87.    
  88.     char* ptr = NULL;
  89.     unsigned short int portValue = (unsigned short int)strtol(port, &ptr, 10);
  90.     if (!ptr)
  91.     {
  92.         fprintf(stderr, "Invalid port %s\n", port);
  93.         exit(EXIT_FAILURE);
  94.     }
  95.     // create
  96.     serverSocket = socket(AF_INET, SOCK_STREAM, 0);
  97.     if (serverSocket == 0) {
  98.         fprintf(stderr, "Bad socket: %s\n", strerror(errno));
  99.         exit(EXIT_FAILURE);
  100.     }
  101.    
  102.     // set server port
  103.     struct sockaddr_in addr;
  104.     memset(&addr, 0, sizeof addr);
  105.     addr.sin_family = AF_INET;
  106.     addr.sin_port = htons(portValue);
  107.     addr.sin_addr.s_addr = htonl(INADDR_ANY);
  108.    
  109.     //bind    
  110.     if (bind(serverSocket, (struct sockaddr *)&addr, sizeof(struct sockaddr))== -1) {
  111.         fprintf(stderr, "Error when binding %s\n", strerror(errno));
  112.         close(serverSocket);
  113.         exit(EXIT_FAILURE);
  114.     }
  115.    
  116.     // listen
  117.     if (listen(serverSocket, SOMAXCONN) == -1) {
  118.         fprintf(stderr, "Error when listening %s\n", strerror(errno));
  119.         close(serverSocket);
  120.         exit(EXIT_FAILURE);
  121.     }
  122.    
  123.     // enable signals
  124.     signal(SIGINT, handleSignal);
  125.     signal(SIGTERM, handleSignal);
  126.     //--------------------------------------------------------------------------------------------------------------------------------
  127.    
  128.     //-------------------------------------------------------- Accept incoming client connections ------------------------------------
  129.     while (1)
  130.     {
  131.         clientSocket = accept(serverSocket, NULL, NULL);
  132.        
  133.         if (clientSocket < 0) {
  134.             fprintf(stderr, "Error when accepting client.");
  135.             break;
  136.         }
  137.        
  138.         char request[1023];
  139.         ssize_t received = recv(clientSocket, request, 1023, 0);
  140.        
  141.         if (received <= 0) {
  142.             shutdown(clientSocket, SHUT_RDWR);
  143.             close(clientSocket);
  144.             continue;
  145.         }
  146.         //-------------------------------------------------------------------------------------------------- Handle request
  147.         // parse first line
  148.         char *ptr = strstr(request, " HTTP/1.1\r\n");
  149.         // if invalid HTTP header, reply 400 error
  150.         if (!ptr) {
  151.             char errorResponse[1023];
  152.             size_t lenghtError = sprintf(errorResponse, "HTTP/1.1 %d %s\r\nConnection: close\r\n\r\n", 400, "Bad Request");
  153.             send(clientSocket, errorResponse, lenghtError, 0);
  154.         }
  155.         // if unsupported HTTP command except GET, reply 501 error
  156.         else if (strstr(request, "GET ") != request) {
  157.             char errorResponse[1023];
  158.             size_t lenghtError = sprintf(errorResponse, "HTTP/1.1 %d %s\r\nConnection: close\r\n\r\n", 501, "Not implemented");
  159.             send(clientSocket, errorResponse, lenghtError, 0);
  160.         }
  161.         // parse target path from the first line
  162.         else
  163.         {
  164.             *ptr = '\0';                            // erase end
  165.             char *pathname = strdup(root);
  166.             strcat(pathname, "/");
  167.             if (strcmp(request + 4, "/") == 0) strcat(pathname, file);  // if "/" is given, set default file
  168.             else strcat(pathname, request + 5);             // otherwise, set given path
  169.             // try to open file
  170.             FILE *fp = fopen(pathname, "r");
  171.             // if failed, reply 404 error
  172.             if (!fp) {
  173.                 char errorResponse[1023];
  174.                 size_t lenghtError = sprintf(errorResponse, "HTTP/1.1 %d %s\r\nConnection: close\r\n\r\n", 404, "Not found");
  175.                 send(clientSocket, errorResponse, lenghtError, 0);
  176.             }
  177.             else
  178.             {
  179.                 // get current timestamp
  180.             char timestamp[1023];
  181.             time_t tmp = time(NULL);
  182.             struct tm t = *localtime(&tmp);
  183.             strftime(timestamp, sizeof(timestamp), "%a, %d %b %Y %T %z", &t);
  184.                 // get content length
  185.                 int content_length = 0;
  186.                 fseek(fp, 0L, SEEK_END);
  187.                 content_length = ftell(fp);
  188.                 fseek(fp, 0L, SEEK_SET);
  189.                 // send HTTP 200 reply
  190.                 char respond[1023];
  191.                 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);
  192.                 send(clientSocket, respond, size, 0);
  193.                 if (content_length > 0) {
  194.                     char data[1023];
  195.                     ssize_t bytes = 0;
  196.                     do{
  197.                         // try to read all data from the file and send to the client
  198.                         bytes = fread(data, 1, 1023, fp);
  199.                         if (bytes > 0) send(clientSocket, data, bytes, 0);
  200.                     } while(bytes > 0);
  201.                 }
  202.                 //close file handle
  203.                 fclose(fp);
  204.             }
  205.         }
  206.         //-------------------------------------------------------------------------------------------------- Handle request over------------------------------------
  207.        
  208.         shutdown(clientSocket, SHUT_RDWR);
  209.         close(clientSocket);
  210.     }
  211.     //--------------------------------------------------------------------------------------------------------------------------------
  212.     return EXIT_SUCCESS;
  213. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement