summaryrefslogtreecommitdiff
path: root/luxio.c
diff options
context:
space:
mode:
Diffstat (limited to 'luxio.c')
-rw-r--r--luxio.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/luxio.c b/luxio.c
index a796292..4490121 100644
--- a/luxio.c
+++ b/luxio.c
@@ -2595,6 +2595,116 @@ luxio_getaddrinfo(lua_State *L)
return 2;
}
+/* Socket-related send and receive functions *********************************/
+
+static int
+luxio_send(lua_State *L)
+{
+ int fd = luaL_checkint(L, 1);
+ size_t count;
+ const char *buf = luaL_checklstring(L, 2, &count);
+ int flags = luaL_optint(L, 3, 0);
+
+ lua_pushinteger(L, send(fd, buf, count, flags));
+ lua_pushinteger(L, errno);
+
+ return 2;
+}
+
+static int
+luxio_sendto(lua_State *L)
+{
+ int fd = luaL_checkint(L, 1);
+ size_t count;
+ const char *buf = luaL_checklstring(L, 2, &count);
+ int flags = luaL_optint(L, 3, 0);
+ struct sockaddr *addr = luaL_checkudata(L, 4, LUXIO_SOCKADDR_METATABLE_NAME);
+ socklen_t l = luxio___sockaddr_len(L, addr);
+
+ lua_pushinteger(L, sendto(fd, buf, count, flags, addr, l));
+ lua_pushinteger(L, errno);
+
+ return 2;
+}
+
+static int
+luxio_recv(lua_State *L)
+{
+ int fd = luaL_checkint(L, 1);
+ int count = luaL_checkint(L, 2);
+ int flags = luaL_optint(L, 3, 0);
+ ssize_t result;
+ char *buf = malloc(count);
+
+ if (buf == NULL) {
+ lua_pushstring(L, "unable to allocate read buffer: memory exhausted");
+ lua_error(L);
+ }
+
+ result = recv(fd, buf, count, flags);
+
+ if (result == -1) {
+ lua_pushinteger(L, result);
+ lua_pushinteger(L, errno);
+ } else {
+ /* sadly there appears to be no way to avoid this copy.
+ * luaL_Buffer actually builds things on the C stack bytes at a time,
+ * and there is no way to pre-allocate a Lua type other than a
+ * userdatum. Additionally, should Lua call its panic function because
+ * it can't allocate memory to copy this into, our buf will be leaked.
+ * We could perhaps fix this with a lot of faff, involving creating
+ * a userdatum for our buffer, and setting a __gc metamethod.
+ */
+ lua_pushlstring(L, buf, result);
+ lua_pushinteger(L, errno);
+ }
+
+ free(buf);
+
+ return 2;
+}
+
+static int
+luxio_recvfrom(lua_State *L)
+{
+ int fd = luaL_checkint(L, 1);
+ int count = luaL_checkint(L, 2);
+ int flags = luaL_optint(L, 3, 0);
+ struct sockaddr_storage addr;
+ socklen_t l = sizeof(addr);
+ ssize_t result;
+ char *buf = malloc(count);
+
+ if (buf == NULL) {
+ lua_pushstring(L, "unable to allocate read buffer: memory exhausted");
+ lua_error(L);
+ }
+
+ result = recvfrom(fd, buf, count, flags, (struct sockaddr *)&addr, &l);
+
+ if (result == -1) {
+ free(buf);
+ lua_pushinteger(L, result);
+ lua_pushinteger(L, errno);
+ return 2;
+ }
+
+ /* sadly there appears to be no way to avoid this copy.
+ * luaL_Buffer actually builds things on the C stack bytes at a time,
+ * and there is no way to pre-allocate a Lua type other than a
+ * userdatum. Additionally, should Lua call its panic function because
+ * it can't allocate memory to copy this into, our buf will be leaked.
+ * We could perhaps fix this with a lot of faff, involving creating
+ * a userdatum for our buffer, and setting a __gc metamethod.
+ */
+ lua_pushlstring(L, buf, result);
+ free(buf);
+ lua_pushinteger(L, errno);
+ luxio__makesockaddr(L, (const struct sockaddr *)&addr, l);
+
+ return 3;
+}
+
/* Poll-binding functions ****************************************************/
#define LUXIO_POLLFD_METATABLE "luxio.pollfdarray"
@@ -3224,6 +3334,11 @@ luxio_functions[] = {
{ "make_sockaddr", luxio_makesockaddr },
+ { "send", luxio_send },
+ { "sendto", luxio_sendto },
+ { "recv", luxio_recv },
+ { "recvfrom", luxio_recvfrom },
+
{ "pollfds_new", luxio_pollfds_new },
{ "pollfds_resize", luxio_pollfds_resize },
{ "pollfds_setslot", luxio_pollfds_set_slot },