summaryrefslogtreecommitdiff
path: root/http.c
blob: f30fe537352a8f3a23da1033de989e2bc66de2c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>

#define BUF_LEN 512
#define PATH_LEN 256
#define PORT "3456"
#define BACKLOG 10

int
main(void){
  struct sockaddr_storage client_addr;
  socklen_t addr_size = sizeof client_addr;
  struct addrinfo hints, *serv_info;
  int sockfd, acpt_fd, yes = 1, err, recv_len, file_len;
  char buf[BUF_LEN], method[16], path[PATH_LEN], *file_buf;
  FILE *file;

  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_flags = AI_PASSIVE;
  hints.ai_socktype = SOCK_STREAM;

  if ((err = getaddrinfo(NULL, PORT, &hints, &serv_info)) != 0) {
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(err));
    return 1;
  }
  if ((sockfd = socket(serv_info->ai_family, serv_info->ai_socktype,
        serv_info->ai_protocol)) < 0) {
    perror("socket");
    exit(1);
  }
  if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0) {
    perror("setsockopt");
    exit(1);
  }
  if (bind(sockfd, serv_info->ai_addr, serv_info->ai_addrlen) < 0) {
    perror("bind");
    exit(1);
  }
  freeaddrinfo(serv_info);

  if (listen(sockfd, BACKLOG) < 0) {
    perror("listen");
    exit(1);
  }

  if ((acpt_fd =
      accept(sockfd, (struct sockaddr *)&client_addr, &addr_size)) < 0) {
    perror("accept");
    exit(1);
  }
  chdir("./resources"); // folder where all files to send are

  while (1) {
    if ((recv_len = recv(acpt_fd, buf, BUF_LEN, 0)) < 0) {
      perror("accept");
      exit(1);
    }
    buf[recv_len] = '\0';

    printf("got request: %s\n", buf);
    sscanf(buf, "%s %s", method, path+1); //+1 as first char needs to be .
    printf("method: %s\n", method);
    if (strcmp(method, "GET") == 0) {
      printf("requested: %s\n\n", path+1);
      if (path[1] == '\0') {
        printf("got empty request\n");
        continue;
      }
      path[0] = '.';

      if ((file = fopen(path, "r")) == NULL) {
        printf("opening \"%s\" didn't work (file nonexistent?)\n\n", path);
        continue;
      }
      fseek(file, 0, SEEK_END);
      file_len = ftell(file);
      rewind(file);

      file_buf = malloc(file_len);
      fread(file_buf, file_len, 1, file);
      fclose(file);
      file_buf[file_len] = '\0';

      if (send(acpt_fd, file_buf, file_len, 0) < 0) {
        perror("send");
        exit(1);
      }

      free(file_buf);
      // prevent data leak by resetting path (a second, empty GET request will
      // otherwise send previous file
      path[0] = path[1] = '\0';
    }
    else
      printf("invalid method\n");
  }
  close(acpt_fd);
  close(sockfd);

  return 0;
}