den4ik2003

Untitled

Mar 16th, 2023
207
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.64 KB | None | 0 0
  1. #include <linux/limits.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <limits.h>
  5. #include <unistd.h>
  6. #include <string.h>
  7. #include <arpa/inet.h>
  8. #include <netinet/in.h>
  9. #include <sys/socket.h>
  10. #include <sys/types.h>
  11. #include <stdbool.h>
  12. #include <fcntl.h>
  13. #include <sys/stat.h>
  14. #include <sys/sendfile.h>
  15. #include <signal.h>
  16.  
  17. #define BUF_SIZE 4096
  18.  
  19. volatile sig_atomic_t sig_int_term = 0;
  20.  
  21. void sig_int_term_handler(int signum) {
  22.   sig_int_term = 1;
  23. }
  24.  
  25. int client_part(int client_fd, char* catalog) {
  26.   char buf_req[BUF_SIZE] = {};
  27.   char other_buf[BUF_SIZE] = {};
  28.   char min_request[BUF_SIZE] = "GET HTTP/1.1";
  29.   int res = read(client_fd, buf_req, sizeof(buf_req));
  30.   if (res < strnlen(min_request, 20)) {
  31.     return 0;
  32.   }
  33.  
  34.   // while (read(client_fd, other_buf, sizeof(other_buf)) != 0) {}
  35.  
  36.   // Extract file name + create path to this file
  37.   char filename[BUF_SIZE] = {};
  38.   int i;
  39.   for (i = 0; buf_req[i + 4] != ' '; ++i) { // 4 так как size("GET ")
  40.     filename[i] = buf_req[i + 4];
  41.   }
  42.   filename[i] = '\0'; // на всякий
  43.   int size = strnlen(catalog, PATH_MAX);
  44.   char filepath[BUF_SIZE + PATH_MAX + 1] = {};
  45.   strncpy(filepath, catalog, PATH_MAX);
  46.   filepath[size] = '/';
  47.   strncpy(filepath + size + 1, filename, BUF_SIZE);
  48.  
  49.   // Check permissions + answer
  50.   if (0 != access(filepath, F_OK)) { // not exists
  51.     dprintf(client_fd, "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n");
  52.     return 0;
  53.   } else if (0 != access(filepath, R_OK)) { // exist but we can't read it
  54.     dprintf(client_fd, "HTTP/1.1 403 Forbidden\r\nContent-Length: 0\r\n\r\n");
  55.     return 0;
  56.   }
  57.   // If we there, this file exists and we can read it, JUST DO IT!!!!!
  58.   int fd = open(filepath, O_RDONLY);
  59.   if (-1 == fd) {
  60.     perror("open");
  61.     return -1;
  62.   }
  63.   struct stat fstat = {};
  64.   if (-1 == stat(filepath, &fstat)) {
  65.     perror("stat");
  66.     return -1;
  67.   }
  68.   int file_size = fstat.st_size;
  69.   off_t shift = 0;
  70.   dprintf(client_fd, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\n\r\n", file_size);
  71.   sendfile(client_fd, fd, &shift, fstat.st_size);
  72.  
  73.   return 0;
  74. }
  75.  
  76. int main(int argc, char** argv) { // 1 - номер порта, 2 - путь до каталога
  77.   if (argc != 3) {
  78.     perror("Incorrect input!");
  79.     exit(0);
  80.   }
  81.   // Привязка сигналов
  82.   struct sigaction sig_int_term_action = {};
  83.   sig_int_term_action.sa_handler = sig_int_term_handler;
  84.  
  85.   sigaction(SIGTERM, &sig_int_term_action, NULL);
  86.   sigaction(SIGINT, &sig_int_term_action, NULL);
  87.  
  88.     // Локалхоста подсоединяем
  89.   long port = strtol(argv[1], NULL, 10);
  90.  
  91.   struct sockaddr_in address = {};
  92.   address.sin_family = AF_INET;
  93.   address.sin_port = htons(port);
  94.   address.sin_addr.s_addr = htonl(INADDR_ANY);
  95.  
  96.   int sockfd = socket(AF_INET, SOCK_STREAM, 0);
  97.   if (-1 == sockfd) {
  98.     perror("sockfd");
  99.     exit(1);
  100.   }
  101.   if (-1 == bind(sockfd, (const struct sockaddr*) &address, sizeof(address))) {
  102.     perror("bind");
  103.     exit(1);
  104.   }
  105.  
  106.   listen(sockfd, SOMAXCONN);
  107.  
  108.   // Работа с клиентом
  109.   while(sig_int_term != 1) {
  110.     // Подключение клиента
  111.     struct sockaddr_in client_addr = {};
  112.     socklen_t addr_len = sizeof(struct sockaddr_in);
  113.     int client_fd = accept(sockfd, (struct sockaddr*)&client_addr, &addr_len);
  114.    
  115.     // Обработка клиента
  116.     client_part(client_fd, argv[2]);
  117.  
  118.     // Отключаем клиента
  119.     shutdown(client_fd, SHUT_RDWR);
  120.     close(client_fd);
  121.   }
  122.  
  123.   // Конец, если мы попали в эту часть, то sig_int_term = 1
  124.   shutdown(sockfd, SHUT_RDWR);
  125.   close(sockfd);
  126.   return 0;
  127. }
Add Comment
Please, Sign In to add comment