summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cfws.c66
-rw-r--r--http.c5
-rw-r--r--http.h5
3 files changed, 64 insertions, 12 deletions
diff --git a/cfws.c b/cfws.c
index bc9d0fa..63a6b19 100644
--- a/cfws.c
+++ b/cfws.c
@@ -1,4 +1,6 @@
#include <arpa/inet.h>
+#include <errno.h>
+#include <linux/limits.h>
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
@@ -6,6 +8,7 @@
#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>
@@ -17,6 +20,8 @@
#define CFWS_DEFAULT_PORT 8080
+size_t file_read(const char *, char **);
+
int initialize_server(int);
void handle_connection();
@@ -41,6 +46,44 @@ int main(int argc, char *argv[])
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;
@@ -81,8 +124,10 @@ int initialize_server(int port)
void handle_connection(int connfd)
{
- char msgbuf[128];
- char *resbuf;
+ char *content_buf;
+ size_t content_len, response_len;
+
+ char resbuf[CFWS_MAX_RESPONSE];
char readbuf[CFWS_MAXREAD];
struct http_request req;
@@ -91,12 +136,17 @@ void handle_connection(int connfd)
req = http_parse_request(readbuf);
- snprintf(msgbuf, 128, "Welcome to %s", req.uri);
-
- http_build_response(&resbuf, HTTP_RESPONSE_OK, msgbuf);
- write(connfd, resbuf, strlen(resbuf));
+ 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);
+ }
- free(resbuf);
+ write(connfd, resbuf, response_len);
http_free_request(&req);
}
-
diff --git a/http.c b/http.c
index d6f495d..b6bad8e 100644
--- a/http.c
+++ b/http.c
@@ -30,8 +30,7 @@ void http_free_request(struct http_request *req)
free(req->uri);
}
-void http_build_response(char **res, enum http_res_code code, const char *msg)
+int http_build_response(char *res, enum http_res_code code, const char *msg, size_t msglen)
{
- *res = malloc(128);
- sprintf(*res, "HTTP/1.1 200 OK\r\n\r\n%s\r\n", msg);
+ return snprintf(res, CFWS_MAX_RESPONSE, "HTTP/1.1 200 OK\r\n\r\n%.*s\r\n", msglen, msg);
}
diff --git a/http.h b/http.h
index b39e271..1e97820 100644
--- a/http.h
+++ b/http.h
@@ -1,7 +1,10 @@
#ifndef _H_HTTP
#define _H_HTTP
+#include <stddef.h>
+
#define CFWS_MAXURI 128
+#define CFWS_MAX_RESPONSE 4096
enum http_req_method {
HTTP_METHOD_GET
@@ -20,6 +23,6 @@ struct http_request {
struct http_request http_parse_request(const char *);
void http_free_request(struct http_request *);
-void http_build_response(char **, enum http_res_code, const char *);
+int http_build_response(char *, enum http_res_code, const char *, size_t);
#endif