diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | cfws.c | 124 | ||||
-rw-r--r-- | file.c | 47 | ||||
-rw-r--r-- | file.h | 8 | ||||
-rw-r--r-- | net.c | 81 | ||||
-rw-r--r-- | net.h | 10 |
6 files changed, 148 insertions, 124 deletions
@@ -4,7 +4,7 @@ LD=gcc CFLAGS=-Wall -Wextra -pedantic -std=c89 -g LDFLAGS= -OBJS=cfws.o http.o +OBJS=cfws.o file.o http.o net.o DESTDIR=/usr/local/bin/ @@ -1,30 +1,13 @@ -#include <arpa/inet.h> -#include <errno.h> -#include <linux/limits.h> -#include <netdb.h> -#include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <sys/ioctl.h> #include <sys/socket.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <sys/types.h> #include <unistd.h> -#include "http.h" - -#define CFWS_MAXCONN 10 /* Max connections allowed by listen(). */ -#define CFWS_MAXREAD 1024 /* Size of buffer used for reading from client. */ +#include "net.h" #define CFWS_DEFAULT_PORT 8080 -size_t file_read(const char *, char **); - -int initialize_server(int); -void handle_connection(); - int main(int argc, char *argv[]) { int port = CFWS_DEFAULT_PORT; @@ -45,108 +28,3 @@ int main(int argc, char *argv[]) close(serverfd); return 0; } - -size_t file_read(const char *uri_path, char **buffer) -{ - FILE *fp; - struct stat statbuf; - char path[PATH_MAX]; - long len; - - /* Prepend the current working directory to the uri path */ - getcwd(path, PATH_MAX); - strncat(path, uri_path, PATH_MAX - 1); - - /* Append 'index.html' to directory paths. */ - stat(path, &statbuf); - if (S_ISDIR(statbuf.st_mode)) - strcat(path, "index.html"); - - fp = fopen(path, "rb"); - if (fp == NULL) { - /* - * File not found is a very common and harmless error, so - * there's no need to print it out every time. - */ - if (errno != ENOENT) - perror("Failed to open file"); - return 0; - } - - fseek(fp, 0, SEEK_END); - len = ftell(fp); - fseek(fp, 0, SEEK_SET); - - *buffer = malloc(len); - fread(*buffer, 1, len, fp); - - fclose(fp); - return len; -} - -int initialize_server(int port) -{ - struct sockaddr_in addr; - int rc; - int sockopts = 1; - int sockfd; - - sockfd = socket(AF_INET, SOCK_STREAM, 0); - if (sockfd == -1) { - perror("Failed to create server socket"); - return -1; - } - - /* Allow the port to be reused, prevents errors when quickly starting - * and restarting the server. */ - /* TODO: Also use SO_REUSEPORT? */ - setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopts, sizeof(int)); - - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_ANY); - addr.sin_port = htons(port); - - rc = bind(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr)); - if (rc == -1) { - perror("Failed to bind server socket"); - return -1; - } - - rc = listen(sockfd, CFWS_MAXCONN); - if (rc == -1) { - perror("Failed to listen on server socket"); - return -1; - } - - return sockfd; -} - -void handle_connection(int connfd) -{ - char *content_buf; - size_t content_len, response_len; - - char resbuf[CFWS_MAX_RESPONSE]; - char readbuf[CFWS_MAXREAD]; - struct http_request req; - - memset(readbuf, 0, CFWS_MAXREAD); - read(connfd, readbuf, CFWS_MAXREAD - 1); - - req = http_parse_request(readbuf); - - content_len = file_read(req.uri, &content_buf); - if (content_len == 0) { - const char *msg = "Could not find the specified file."; - response_len = http_build_response(resbuf, - HTTP_RESPONSE_NOTFOUND, msg, strlen(msg)); - } else { - response_len = http_build_response(resbuf, HTTP_RESPONSE_OK, - content_buf, content_len); - free(content_buf); - } - - write(connfd, resbuf, response_len); - http_free_request(&req); -} @@ -0,0 +1,47 @@ +#include "file.h" + +#include <errno.h> +#include <linux/limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> + +size_t file_read(const char *uri_path, char **buffer) +{ + FILE *fp; + struct stat statbuf; + char path[PATH_MAX]; + long len; + + /* Prepend the current working directory to the uri path */ + getcwd(path, PATH_MAX); + strncat(path, uri_path, PATH_MAX - 1); + + /* Append 'index.html' to directory paths. */ + stat(path, &statbuf); + if (S_ISDIR(statbuf.st_mode)) + strcat(path, "index.html"); + + fp = fopen(path, "rb"); + if (fp == NULL) { + /* + * File not found is a very common and harmless error, so + * there's no need to print it out every time. + */ + if (errno != ENOENT) + perror("Failed to open file"); + return 0; + } + + fseek(fp, 0, SEEK_END); + len = ftell(fp); + fseek(fp, 0, SEEK_SET); + + *buffer = malloc(len); + fread(*buffer, 1, len, fp); + + fclose(fp); + return len; +} @@ -0,0 +1,8 @@ +#ifndef _H_FILE +#define _H_FILE + +#include <stddef.h> + +size_t file_read(const char *, char **); + +#endif @@ -0,0 +1,81 @@ +#include "net.h" + +#include <arpa/inet.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <unistd.h> + +#include "file.h" +#include "http.h" + +int initialize_server(int port) +{ + struct sockaddr_in addr; + int rc; + int sockopts = 1; + int sockfd; + + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd == -1) { + perror("Failed to create server socket"); + return -1; + } + + /* Allow the port to be reused, prevents errors when quickly starting + * and restarting the server. */ + /* TODO: Also use SO_REUSEPORT? */ + setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopts, sizeof(int)); + + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_port = htons(port); + + rc = bind(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr)); + if (rc == -1) { + perror("Failed to bind server socket"); + return -1; + } + + rc = listen(sockfd, CFWS_MAXCONN); + if (rc == -1) { + perror("Failed to listen on server socket"); + return -1; + } + + return sockfd; +} + +void handle_connection(int connfd) +{ + char *content_buf; + size_t content_len, response_len; + + char resbuf[CFWS_MAX_RESPONSE]; + char readbuf[CFWS_MAXREAD]; + struct http_request req; + + memset(readbuf, 0, CFWS_MAXREAD); + read(connfd, readbuf, CFWS_MAXREAD - 1); + + req = http_parse_request(readbuf); + + content_len = file_read(req.uri, &content_buf); + if (content_len == 0) { + const char *msg = "Could not find the specified file."; + response_len = http_build_response(resbuf, + HTTP_RESPONSE_NOTFOUND, msg, strlen(msg)); + } else { + response_len = http_build_response(resbuf, HTTP_RESPONSE_OK, + content_buf, content_len); + free(content_buf); + } + + write(connfd, resbuf, response_len); + http_free_request(&req); +} @@ -0,0 +1,10 @@ +#ifndef _H_NET +#define _H_NET + +#define CFWS_MAXCONN 10 /* Max connections allowed by listen(). */ +#define CFWS_MAXREAD 1024 /* Size of buffer used for reading from client. */ + +int initialize_server(int); +void handle_connection(int); + +#endif |