#include #include #include #include #include #include #include #include #include #include #include #include typedef enum { GET = 0, POST = 1, UNKNOWN = -1 } HTTP_METHODS; int shsd_sendfile(int in_fd, FILE *ou_fd) { struct stat s; int stat_result = fstat(fileno(ou_fd), &s); if (stat_result != 0) { perror("fstat"); return -1; } sendfile(in_fd, fileno(ou_fd), NULL, s.st_size); return 0; } HTTP_METHODS get_require_method(char *method) { HTTP_METHODS m; if (strcmp(method, "GET") == 0) { return m = GET; } if (strcmp(method, "POST") == 0) { return m = POST; } else { return m = UNKNOWN; } } int check_file_stat(const char *path, int fd) { struct stat st; if (stat(path, &st) == -1 && S_ISDIR(st.st_mode)) { return -1; } return 0; } int handle_client(int client_fd, char *buf) { char method[16], path[256]; if (sscanf(buf, "%15s %255s", method, path) < 2) { close(client_fd); return -1; } if (strcmp(path, "/") == 0) { strcpy(path, "/index.html"); } char local_path[1024]; snprintf(local_path, sizeof(local_path), "./www%s", path); FILE *fp = fopen(local_path, "r"); if (!fp) { perror("fopen"); fp = fopen("./www/404.html", "r"); shsd_sendfile(client_fd, fp); return -1; } shsd_sendfile(client_fd, fp); return 0; } int main(int argc, char **argv) { struct addrinfo hints, *res, *servinfo; struct sockaddr_storage their_addr; socklen_t addr_size; int sockfd, new_fd; int yes = 1; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; // use IPv4 or IPv6, whichever hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; // fill in my IP for me getaddrinfo(NULL, argv[1], &hints, &res); sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) { perror("setsockopt"); exit(1); } if (bind(sockfd, res->ai_addr, res->ai_addrlen) == -1) { perror("bind"); close(sockfd); exit(1); } if (listen(sockfd, 10) == -1) { perror("listen"); close(sockfd); exit(1); } addr_size = sizeof(their_addr); char buf[1024]; memset(buf, 0, 1024); int recv_result; while (1) { new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &addr_size); recv_result = recv(new_fd, (void *)buf, 1024, 0); if (recv_result == -1) { perror("recv"); return -1; } for (int i = 0; i < sizeof(buf); i++) { printf("%c", buf[i]); } if (strncmp(buf, "GET", 3) == 0) { char *http_status = "HTTP/1.1 200 OK\r\n"; char *http_content_type = "text/html\r\n\r\n"; printf("Received GET request.\n"); send(new_fd, http_status, strlen(http_status), 0); send(new_fd, http_content_type, strlen(http_content_type), 0); FILE *index_fd = fopen("./index.html", "r"); struct stat stat_buf; shsd_sendfile(new_fd, index_fd, &stat_buf); } memset(buf, 0, 1024); close(new_fd); } close(sockfd); close(new_fd); return 0; }