summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmil Renner Berthing <esmil@mailme.dk>2013-01-16 11:41:14 +0100
committerEmil Renner Berthing <esmil@mailme.dk>2013-01-27 23:08:57 +0100
commitc20b177f6f1a5542d750d30ffdc96e18c5090d24 (patch)
tree8c89ec48fd734006a066e80846c56025566f4af5
parentf27e9657213a42fb500eb32f089d0df68e75f71c (diff)
downloadlem-c20b177f6f1a5542d750d30ffdc96e18c5090d24.tar.gz
lem-c20b177f6f1a5542d750d30ffdc96e18c5090d24.tar.xz
lem-c20b177f6f1a5542d750d30ffdc96e18c5090d24.zip
io: add stream:getpeer()
-rw-r--r--lem/io/core.c7
-rw-r--r--lem/io/stream.c81
-rwxr-xr-xtest/htest.lua9
3 files changed, 95 insertions, 2 deletions
diff --git a/lem/io/core.c b/lem/io/core.c
index 867c745..459fa2a 100644
--- a/lem/io/core.c
+++ b/lem/io/core.c
@@ -16,6 +16,7 @@
* License along with LEM. If not, see <http://www.gnu.org/licenses/>.
*/
+#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
@@ -32,6 +33,7 @@
#if defined(__FreeBSD__) || defined(__APPLE__)
#include <sys/un.h>
+#include <sys/ucred.h>
#include <netinet/in.h>
#ifndef UNIX_PATH_MAX
#define UNIX_PATH_MAX 104
@@ -319,6 +321,9 @@ luaopen_lem_io_core(lua_State *L)
/* mt.uncork = <stream_uncork> */
lua_pushcfunction(L, stream_uncork);
lua_setfield(L, -2, "uncork");
+ /* mt.getpeer = <stream_getpeer> */
+ lua_pushcfunction(L, stream_getpeer);
+ lua_setfield(L, -2, "getpeer");
/* mt.sendfile = <stream_sendfile> */
lua_pushcfunction(L, stream_sendfile);
lua_setfield(L, -2, "sendfile");
@@ -402,7 +407,7 @@ luaopen_lem_io_core(lua_State *L)
lua_getfield(L, -2, "Server"); /* upvalue 1 = Server */
lua_pushcclosure(L, unix_listen, 1);
lua_setfield(L, -2, "listen");
- /* insert the tcp table */
+ /* insert the unix table */
lua_setfield(L, -2, "unix");
return 1;
diff --git a/lem/io/stream.c b/lem/io/stream.c
index b988278..1c37eaa 100644
--- a/lem/io/stream.c
+++ b/lem/io/stream.c
@@ -325,6 +325,87 @@ stream_uncork(lua_State *T)
return stream_setcork(T, 0);
}
+static int
+stream_getpeer(lua_State *T)
+{
+ struct stream *s;
+ union {
+ struct sockaddr all;
+ struct sockaddr_in in;
+ struct sockaddr_in6 in6;
+ } addr;
+ socklen_t len;
+
+ luaL_checktype(T, 1, LUA_TUSERDATA);
+ s = lua_touserdata(T, 1);
+ if (!s->open)
+ return io_closed(T);
+
+ len = sizeof(addr);
+ if (getpeername(s->r.fd, &addr.all, &len))
+ return io_strerror(T, errno);
+
+ switch (addr.all.sa_family) {
+ case AF_UNIX: {
+#if defined(__FreeBSD__) || defined(__APPLE__)
+ struct xucred cred;
+
+ len = sizeof(struct xucred);
+ if (getsockopt(s->r.fd, 0, LOCAL_PEERCRED, &cred, &len))
+ return io_strerror(T, errno);
+
+ if (len != sizeof(struct xucred) ||
+ cred.cr_version != XUCRED_VERSION) {
+ lua_pushnil(T);
+ lua_pushliteral(T, "version mismatch");
+ return 2;
+ }
+
+ lua_pushliteral(T, "*unix");
+ lua_pushnumber(T, cred.cr_uid);
+ lua_pushnumber(T, cred.cr_gid);
+#else
+ struct ucred cred;
+
+ len = sizeof(struct ucred);
+ if (getsockopt(s->r.fd, SOL_SOCKET, SO_PEERCRED, &cred, &len))
+ return io_strerror(T, errno);
+
+ lua_pushliteral(T, "*unix");
+ lua_pushnumber(T, cred.uid);
+ lua_pushnumber(T, cred.gid);
+#endif
+ return 3;
+ }
+
+ case AF_INET: {
+ char buf[INET_ADDRSTRLEN];
+
+ if (inet_ntop(addr.in.sin_family, &addr.in.sin_addr,
+ buf, sizeof(buf)) == NULL)
+ return io_strerror(T, errno);
+
+ lua_pushstring(T, buf);
+ lua_pushnumber(T, ntohs(addr.in.sin_port));
+ return 2;
+ }
+
+ case AF_INET6: {
+ char buf[INET6_ADDRSTRLEN];
+
+ if (inet_ntop(addr.in6.sin6_family, &addr.in6.sin6_addr,
+ buf, sizeof(buf)) == NULL)
+ return io_strerror(T, errno);
+
+ lua_pushstring(T, buf);
+ lua_pushnumber(T, ntohs(addr.in6.sin6_port));
+ return 2;
+ }
+ }
+
+ return io_strerror(T, EINVAL);
+}
+
struct sfhandle {
struct lem_async a;
struct stream *s;
diff --git a/test/htest.lua b/test/htest.lua
index 2be8e6c..a94e4c6 100755
--- a/test/htest.lua
+++ b/test/htest.lua
@@ -21,10 +21,12 @@ package.path = '?.lua'
package.cpath = '?.so'
local utils = require 'lem.utils'
+local io = require 'lem.io'
local hathaway = require 'lem.hathaway'
hathaway.import()
GET('/', function(req, res)
+ print(req.client:getpeer())
res.status = 302
res.headers['Location'] = '/dump'
end)
@@ -145,7 +147,12 @@ GETM('^/hello/([^/]+)$', function(req, res, name)
end)
hathaway.debug = print
-Hathaway('*', arg[1] or 8080)
+if arg[1] == 'socket' then
+ local sock = assert(io.unix.listen('socket', 666))
+ Hathaway(sock)
+else
+ Hathaway('*', arg[1] or '8080')
+end
utils.exit(0) -- otherwise open connections will keep us running
-- vim: syntax=lua ts=2 sw=2 noet: