summaryrefslogtreecommitdiffhomepage
path: root/response.c
diff options
context:
space:
mode:
Diffstat (limited to 'response.c')
-rw-r--r--response.c139
1 files changed, 0 insertions, 139 deletions
diff --git a/response.c b/response.c
deleted file mode 100644
index 4f70b0d..0000000
--- a/response.c
+++ /dev/null
@@ -1,139 +0,0 @@
-#include "response.h"
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <lua.h>
-
-/// Sends a response based on the current top value on the stack.
-/// \param L Lua state to send response for
-/// \param fd File descriptor of a socket to write to
-/// \return Bytes written or -1 on error
-/// \see write(2)
-// TODO: Consider splitting response_send into smaller functions.
-int response_send(lua_State * L, const int fd)
-{
- static const char * error_response =
- "HTTP/1.1 500\r\n"
- "Connection: close\r\n"
- "\r\n";
-
- if (0 == lua_istable(L, -1) || 0 == lua_checkstack(L, 5))
- {
- lua_pop(L, 1);
- return write(fd, error_response, strlen(error_response));
- }
-
- int bytes_total = 2048 * sizeof(char);
- int bytes_used = 0;
- char * buffer = malloc(bytes_total);
- char * new_buffer = NULL;
-
- lua_pushliteral(L, "status");
- lua_gettable(L, -2);
- const lua_Integer status = lua_tointeger(L, -1);
- lua_pop(L, 1);
-
- if (0 == status || NULL == buffer)
- {
- free(buffer);
- lua_pop(L, 1);
- return write(fd, error_response, strlen(error_response));
- }
-
- bytes_used = snprintf(buffer, bytes_total, "HTTP/1.1 %d\r\n\r\n", (int) status) - 2;
-
- lua_pushliteral(L, "headers");
- lua_gettable(L, -2);
-
- if (0 == lua_istable(L, -1))
- {
- const int result = write(fd, buffer, bytes_used + 2);
- free(buffer);
- lua_pop(L, 2);
- return result;
- }
-
- static const char * header_pattern = "%s: %s\r\n";
-
- lua_pushnil(L);
- while (0 != lua_next(L, -2) && 0 != lua_isstring(L, -2))
- {
- const char * key = lua_tostring(L, -2);
- const char * value = lua_tostring(L, -1); // TODO: Check the type of the header's value?
- const int bytes_left = bytes_total - bytes_used;
- int new_bytes = snprintf(buffer + bytes_used, bytes_left, header_pattern, key, value);
- while (bytes_left <= new_bytes)
- {
- bytes_total += 2048;
- if (65536 < bytes_total)
- {
- free(buffer);
- lua_pop(L, 4);
- return write(fd, error_response, strlen(error_response));
- }
- new_buffer = realloc(buffer, bytes_total); // TODO: Realloc and error handling involves duplication.
- if (NULL == new_buffer)
- {
- free(buffer);
- lua_pop(L, 4);
- return write(fd, error_response, strlen(error_response));
- }
- buffer = new_buffer;
- new_bytes = snprintf(buffer + bytes_used, bytes_left, header_pattern, key, value);
- }
- bytes_used += new_bytes;
- lua_pop(L, 1);
- }
-
- if (bytes_total < bytes_used + 2)
- {
- bytes_total += 2;
- new_buffer = realloc(buffer, bytes_total);
- if (NULL == new_buffer)
- {
- lua_pop(L, 2);
- return write(fd, error_response, strlen(error_response));
- }
- buffer = new_buffer;
- }
-
- lua_pop(L, 1);
- buffer[bytes_used] = '\r';
- buffer[bytes_used + 1] = '\n';
- bytes_used += 2;
-
- lua_pushliteral(L, "data");
- lua_gettable(L, -2);
- size_t data_length = 0;
- const char * data = lua_tolstring(L, -1, &data_length);
-
- if (NULL != data && 0 < data_length)
- {
- // TODO: There are quite a few parts which could be moved out of this function.
- if (bytes_total < bytes_used + (int) data_length)
- {
- bytes_total += data_length;
- new_buffer = realloc(buffer, bytes_total);
- if (NULL == new_buffer)
- {
- free(buffer);
- lua_pop(L, 2);
- return write(fd, error_response, strlen(error_response));
- }
- buffer = new_buffer;
- }
-
- memcpy(buffer + bytes_used, data, data_length);
- bytes_used += data_length;
- }
-
- int result = write(fd, buffer, bytes_used);
- free(buffer); // TODO: Don't free the buffer if EAGAIN or EWOULDBLOCK, so it can be reused.
- lua_pop(L, 2);
-
- return result;
-}