summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--http.c59
-rw-r--r--http.h8
-rw-r--r--plop.c30
3 files changed, 52 insertions, 45 deletions
diff --git a/http.c b/http.c
index c61b47b..ca7dcdf 100644
--- a/http.c
+++ b/http.c
@@ -7,6 +7,8 @@
#include <string.h>
#include <unistd.h>
+static const int REQUEST_DATA_SIZE = 4096;
+
const char * status_str[] = {
[STATUS_OK] = "200 OK",
[STATUS_BAD_REQUEST] = "400 Bad Request",
@@ -18,7 +20,7 @@ const char * status_str[] = {
};
/// Allocates and initializes request structure.
-/// \return Pointer to initialized request
+/// \return Pointer to initialized request or NULL in case of an error
/// \see /free_request
struct request * new_request(void)
{
@@ -30,7 +32,15 @@ struct request * new_request(void)
}
memset(request, 0, sizeof(struct request));
- request->step = parse_method;
+ request->step = parse_step_method;
+
+ request->data = malloc(REQUEST_DATA_SIZE);
+
+ if (NULL == request->data)
+ {
+ free(request);
+ return NULL;
+ }
return request;
}
@@ -42,7 +52,7 @@ void free_request(struct request * request)
{
if (NULL != request->data)
{
- // TODO: free(request->data); data lifetime is now managed by plop, move it here
+ free(request->data);
}
if (NULL != request->headers)
@@ -92,15 +102,13 @@ int respond_with_body(const int fd, const enum status status, const char * body,
/// Collects request between calls to `poll`.
/// \param fd Client socket
-/// \param request Buffer with the request content
+/// \param request Pointer to current request context of handled client
/// \return Number of bytes parsed, -1 if an error occured or 0 if expects more data
-int collect_request(const int fd, char ** request)
+int parse_request(const int fd, struct request ** request)
{
- static const int size = 4096;
-
if (NULL == *request)
{
- *request = malloc(size);
+ *request = new_request();
if (NULL == *request)
{
return -1;
@@ -108,30 +116,17 @@ int collect_request(const int fd, char ** request)
}
// TODO: Expand buffer until EAGAIN or arbitrary limit
- int length = read(fd, *request, size - 1);
+ int length = read(fd, (*request)->data, REQUEST_DATA_SIZE - 1);
if (0 == length || (-1 == length && EWOULDBLOCK != errno && EAGAIN != errno))
{
return -1; // TODO: Handle errors properly
}
- // TODO: Use struct request in plop
- struct request * debug = new_request();
- debug->data = *request;
- debug->length = length;
- debug->step(debug);
-
- printf(
- "(%.*s) [%.*s] %.*s\n",
- debug->version.length, debug->data + debug->version.start,
- debug->method.length, debug->data + debug->method.start,
- debug->path.length, debug->data + debug->path.start);
-
- free_request(debug);
-
- (*request)[length] = 0;
+ (*request)->data[length] = 0;
+ (*request)->length = length;
- return length;
+ return (*request)->step(*request);
}
@@ -199,7 +194,7 @@ static int read_rest_of_line(struct request * request)
/// Parses method field of the request.
/// \param request Request to process
/// \return -1 if an error has occured, 0 if too little data available or total number of bytes processed
-int parse_method(struct request * request)
+int parse_step_method(struct request * request)
{
request->method.length = read_until_char(request, ' ');
@@ -208,16 +203,16 @@ int parse_method(struct request * request)
return 0;
}
- request->step = parse_path;
+ request->step = parse_step_path;
- return parse_path(request);
+ return parse_step_path(request);
}
/// Parses path field of the request.
/// \param request Request to process
/// \return -1 if an error has occured, 0 if too little data available or total number of bytes processed
// TODO: Consider spliting path into an actual path and arguments in this stage
-int parse_path(struct request * request)
+int parse_step_path(struct request * request)
{
if (0 >= request->path.start)
{
@@ -237,16 +232,16 @@ int parse_path(struct request * request)
}
request->path.length = request->position - request->path.start;
- request->step = parse_version;
+ request->step = parse_step_version;
- return parse_version(request);
+ return parse_step_version(request);
}
/// Parses and verifies http version field of the request.
/// \param request Request to process
/// \return -1 if an error has occured, 0 if too little data available or total number of bytes processed
// TODO: Return -1 if version is unsupported, meaning other than HTTP/1.1
-int parse_version(struct request * request)
+int parse_step_version(struct request * request)
{
if (0 >= request->version.start)
{
diff --git a/http.h b/http.h
index 4629846..90f4bbf 100644
--- a/http.h
+++ b/http.h
@@ -45,10 +45,10 @@ void free_request(struct request *);
int respond_only_status(int, enum status);
int respond_with_body(int, enum status, const char *, int);
-int collect_request(int, char **);
+int parse_request(int, struct request **);
-int parse_method(struct request *);
-int parse_path(struct request *);
-int parse_version(struct request *);
+int parse_step_method(struct request *);
+int parse_step_path(struct request *);
+int parse_step_version(struct request *);
#endif // HTTP_H
diff --git a/plop.c b/plop.c
index 1dff60f..963b7b9 100644
--- a/plop.c
+++ b/plop.c
@@ -5,6 +5,7 @@
#include <lualib.h>
#include <netdb.h>
#include <poll.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
@@ -82,11 +83,11 @@ int make_server(const char * node, const char * service)
/// `pfd` must be at least `shift_by + 1`-th element of the array.
/// \param L Server's Lua state
/// \param pfd Element in array processed by poll
-/// \param data Pointer to data associated with the client
+/// \param request Pointer to request context associated with current client
/// \param shift_by Element will be moved by in array this many indices
/// \return Shift value for next handler
/// \see poll(2)
-int handle_client(lua_State * L, struct pollfd * pfd, char ** data, const int shift_by)
+int handle_client(lua_State * L, struct pollfd * pfd, struct request ** request, const int shift_by)
{
if (0 == pfd->revents)
{
@@ -98,14 +99,22 @@ int handle_client(lua_State * L, struct pollfd * pfd, char ** data, const int sh
return -1; // TODO: Handle errors properly
}
- if (-1 == collect_request(pfd->fd, data))
+ if (-1 == parse_request(pfd->fd, request))
{
respond_only_status(pfd->fd, STATUS_BAD_REQUEST);
return -1; // TODO: Handle errors properly
}
+ // TODO: Remove debug information or move to logging
+ printf(
+ "(%.*s) [%.*s] %.*s\n",
+ (*request)->version.length, (*request)->data + (*request)->version.start,
+ (*request)->method.length, (*request)->data + (*request)->method.start,
+ (*request)->path.length, (*request)->data + (*request)->path.start);
+
+ // TODO: Use results from parsing instead of raw data
lua_getglobal(L, "Handler");
- lua_pushstring(L, *data);
+ lua_pushlstring(L, (*request)->data, (*request)->length);
lua_call(L, 1, 1);
size_t length;
@@ -124,8 +133,11 @@ int handle_client(lua_State * L, struct pollfd * pfd, char ** data, const int sh
(pfd - shift_by)->fd = -1;
(pfd - shift_by)->events = pfd->events;
- free(*data);
- *data = NULL;
+ if (NULL != *request)
+ {
+ free_request(*request);
+ *request = NULL;
+ }
return shift_by + 1;
}
@@ -179,10 +191,10 @@ int main(int argc, char ** argv)
static const int max_clients = 200;
int fdc = 0;
- char * data[max_clients];
+ struct request * requests[max_clients];
struct pollfd fdv[max_clients];
- memset(data, 0, sizeof(data));
+ memset(requests, 0, sizeof(requests));
memset(fdv, 0, sizeof(fdv));
fdv[0].fd = make_server(NULL, argv[1]);
@@ -200,7 +212,7 @@ int main(int argc, char ** argv)
for (int i = 1; i < fdc; ++i)
{
- shift_by = handle_client(L, &fdv[i], &data[i], shift_by);
+ shift_by = handle_client(L, &fdv[i], &requests[i], shift_by);
}
fdc = handle_server(fdv, fdc - shift_by, max_clients);