summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--default.lua8
-rw-r--r--plop.c8
-rw-r--r--stream.c139
-rw-r--r--stream.h5
4 files changed, 148 insertions, 12 deletions
diff --git a/default.lua b/default.lua
index 7100927..56e5082 100644
--- a/default.lua
+++ b/default.lua
@@ -32,6 +32,10 @@ return function (stream)
headers_table = HEADER:format(headers_table, header, value)
end
local response = RESPONSE:format(method, path, version, headers_table)
- local headers = {Connection="close", ["Content-Length"]=#response, ["Content-Type"]="text/html"}
- return {status=status, headers=headers, data=response}
+ stream:write(
+ "HTTP/1.1 ", status, "\r\n",
+ "Connection: close\r\n",
+ "Content-Length: ", #response, "\r\n",
+ "Content-Type: text/html\r\n\r\n", response)
+ stream:flush()
end
diff --git a/plop.c b/plop.c
index 34c8d06..6c2717b 100644
--- a/plop.c
+++ b/plop.c
@@ -164,14 +164,6 @@ int plop_handle_client(lua_State * L, struct epoll_event * event)
{
case LUA_OK:
{
- int n = lua_gettop(c->L);
-
- if (0 == n)
- {
- lua_pushnil(c->L);
- }
-
- response_send(c->L, c->fd);
connection_free(L, c);
return 0;
}
diff --git a/stream.c b/stream.c
index d456619..0863cfd 100644
--- a/stream.c
+++ b/stream.c
@@ -38,11 +38,15 @@ int stream_push_new(lua_State * L, const int fd)
lua_rawset(L, -3);
lua_pushliteral(L, "write");
- lua_pushnil(L); // TODO: Implement writing operation.
+ lua_pushcfunction(L, stream_write);
lua_rawset(L, -3);
lua_pushliteral(L, "flush");
- lua_pushnil(L); // TODO: Implement flush for output buffer.
+ lua_pushcfunction(L, stream_flush);
+ lua_rawset(L, -3);
+
+ lua_pushliteral(L, "flush");
+ lua_pushcfunction(L, stream_flush);
lua_rawset(L, -3);
}
lua_rawset(L, -3);
@@ -262,3 +266,134 @@ int stream_readk(lua_State * L, int status, lua_KContext ctx)
return lua_gettop(L);
}
+
+/// Writes to output buffer.
+/// \param L Lua state in which Stream resides
+/// \return Number of the results pushed to the stack
+int stream_write(lua_State * L)
+{
+ const int n = lua_gettop(L);
+ if (2 > n)
+ {
+ lua_pushliteral(L, "At least two arguments expected");
+ return lua_error(L);
+ }
+
+ struct stream * s = lua_touserdata(L, 1);
+
+ if (NULL == s)
+ {
+ lua_pushliteral(L, "Missing stream argument");
+ return lua_error(L);
+ }
+
+ if (NULL == s->out.data)
+ {
+ void * buffer = malloc(1024);
+
+ if (NULL == buffer)
+ {
+ lua_pushliteral(L, "Could not allocate buffer for stream");
+ return lua_error(L);
+ }
+
+ s->out.data = buffer;
+ s->out.allocated = 1024;
+ s->out.length = 0;
+ s->out.offset = 0;
+ s->out.next = 0;
+ }
+
+ for (int i = 2; n >= i; ++i)
+ {
+ size_t data_length;
+ const char * data = lua_tolstring(L, i, &data_length);
+ const int free_space = s->out.allocated - s->out.length;
+
+ if (free_space >= (int) data_length)
+ {
+ memcpy(&s->out.data[s->out.length], data, data_length);
+ s->out.length += (int) data_length;
+ }
+ else
+ {
+ // TODO: grow
+ }
+ }
+
+ lua_pop(L, n);
+ return 0;
+}
+
+/// Flushes the contents of output buffer writing it to the socket.
+/// \param L Lua state in which Stream resides
+/// \return Number of the results pushed to the stack
+int stream_flush(lua_State * L)
+{
+ const int n = lua_gettop(L);
+
+ if (1 != n)
+ {
+ lua_pushliteral(L, "Expected one argument");
+ return lua_error(L);
+ }
+
+ struct stream * s = lua_touserdata(L, 1);
+
+ if (NULL == s)
+ {
+ lua_pushliteral(L, "Missing stream argument");
+ return lua_error(L);
+ }
+
+ const int bytes_written = write(s->fd, s->out.data, s->out.length);
+
+ if (-1 == bytes_written)
+ {
+ // TODO: Errors and yield
+ }
+ else
+ {
+ s->out.length -= bytes_written;
+ }
+
+ lua_pop(L, 1);
+ return 0;
+}
+
+/// Continuation of the flush operation.
+/// \param L Lua state in which Stream resides
+/// \param status Unused
+/// \param ctx TODO
+/// \return Number of the results pushed to the stack
+int stream_flushk(lua_State * L, const int status, lua_KContext ctx)
+{
+ return 0;
+}
+
+/// Discards the contents of output buffer without writing it anywhere.
+/// \param L Lua state in which Stream resides
+/// \return Number of the results pushed to the stack
+int stream_discard(lua_State * L)
+{
+ const int n = lua_gettop(L);
+
+ if (1 != n)
+ {
+ lua_pushliteral(L, "Expected one argument");
+ return lua_error(L);
+ }
+
+ struct stream * s = lua_touserdata(L, 1);
+
+ if (NULL == s)
+ {
+ lua_pushliteral(L, "Missing stream argument");
+ return lua_error(L);
+ }
+
+ s->out.length = 0;
+
+ lua_pop(L, 1);
+ return 0;
+}
diff --git a/stream.h b/stream.h
index f1bc32c..5119fcc 100644
--- a/stream.h
+++ b/stream.h
@@ -15,9 +15,14 @@ struct stream
{
int fd;
struct buffer in;
+ struct buffer out;
};
int stream_push_new(lua_State *, const int);
int stream_gc(lua_State *);
int stream_read(lua_State *);
int stream_readk(lua_State *, const int, lua_KContext);
+int stream_write(lua_State *);
+int stream_flush(lua_State *);
+int stream_flushk(lua_State *, const int, lua_KContext);
+int stream_discard(lua_State *);