summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Kendrick (plinth) <rjek@rjek.com>2013-11-26 20:22:40 +0000
committerRob Kendrick (plinth) <rjek@rjek.com>2013-11-26 20:22:40 +0000
commit3b7f8babc8f2f8ef635b9fb3d44090f8c019a455 (patch)
treeb2b82bd056cd2827ebe82eaff49912a8e9b5056b
parent785c8fadf519118a9c74e2bbc4f85e27c25a5f0f (diff)
downloadluxio-3b7f8babc8f2f8ef635b9fb3d44090f8c019a455.tar.bz2
send(to), recv(from) in Luxio, and simple bindings to send and recv.
-rw-r--r--luxio.c115
-rw-r--r--luxio/simple.lua36
-rw-r--r--luxio_constants.h.in16
3 files changed, 165 insertions, 2 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 },
diff --git a/luxio/simple.lua b/luxio/simple.lua
index 8d1dbd0..b5d99bd 100644
--- a/luxio/simple.lua
+++ b/luxio/simple.lua
@@ -231,6 +231,10 @@ local l_fcntl = l.fcntl
local l_setsockopt = l.setsockopt
local l_getsockopt = l.getsockopt
local l_getaddrinfo = l.getaddrinfo
+local l_send = l.send
+local l_sendto = l.sendto
+local l_recv = l.recv
+local l_recvfrom = l.recvfrom
local l_gai_strerror = l.gai_strerror
local l_connect = l.connect
local l_bit_bor = l.bit.bor
@@ -296,7 +300,7 @@ end
local flag_prefixes = {
"O_", "SEEK_", "SPLICE_F_", "S_", "F_", "PF_", "AF_", "IPPROTO_", "SOCK_",
- "SHUT_", "SO_", "TCP_", "AI_", "POLL", "LOG_", "EXIT_"
+ "SHUT_", "SO_", "TCP_", "AI_", "POLL", "LOG_", "EXIT_", "MSG_"
}
local function flags_find_flag(f)
@@ -1024,6 +1028,34 @@ local function mconnect(o, address, port)
return true
end
+local function msend(o, buf, f)
+ sio_check_mt(o)
+ assert(type(buf) == "string")
+ f = flags(f or "")
+
+ local r, errno = l_send(o.fd, buf, f);
+
+ if r < 0 then
+ return err("send", errno);
+ end
+
+ return r
+end
+
+local function mrecv(o, count, f)
+ sio_check_mt(o)
+ assert(type(count) == "number")
+ f = flags(f or "")
+
+ local r, errno = l_recv(o.fd, count, f);
+
+ if r == -1 then
+ return err("recv", errno);
+ end
+
+ return r
+end
+
descriptor_mt = {
close = close,
nogc = nogc,
@@ -1046,6 +1078,8 @@ descriptor_mt = {
bind = mbind,
listen = mlisten,
connect = mconnect,
+ send = msend,
+ recv = mrecv,
__tostring = function(x)
return ("file descriptor: %s (%s)"):format(
diff --git a/luxio_constants.h.in b/luxio_constants.h.in
index 07a4f03..cf5a555 100644
--- a/luxio_constants.h.in
+++ b/luxio_constants.h.in
@@ -158,7 +158,21 @@ static const struct {
E(AI_CANONNAME),
E(AI_PASSIVE),
- /* poll-related defines */
+? E(MSG_CONFIRM),
+? E(MSG_DONTROUTE),
+? E(MSG_DONTWAIT),
+? E(MSG_EOR),
+? E(MSG_MORE),
+? E(MSG_NOSIGNAL),
+? E(MSG_OOB),
+? E(MSG_CMSG_CLOEXEC),
+? E(MSG_ERRQUEUE),
+? E(MSG_PEEK),
+? E(MSG_TRUNC),
+? E(MSG_WAITALL),
+
+
+ /* poll-related defines */
E(POLLIN),
E(POLLPRI),
E(POLLOUT),