From c20b177f6f1a5542d750d30ffdc96e18c5090d24 Mon Sep 17 00:00:00 2001 From: Emil Renner Berthing Date: Wed, 16 Jan 2013 11:41:14 +0100 Subject: io: add stream:getpeer() --- lem/io/core.c | 7 ++++- lem/io/stream.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ test/htest.lua | 9 ++++++- 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 . */ +#define _GNU_SOURCE #include #include #include @@ -32,6 +33,7 @@ #if defined(__FreeBSD__) || defined(__APPLE__) #include +#include #include #ifndef UNIX_PATH_MAX #define UNIX_PATH_MAX 104 @@ -319,6 +321,9 @@ luaopen_lem_io_core(lua_State *L) /* mt.uncork = */ lua_pushcfunction(L, stream_uncork); lua_setfield(L, -2, "uncork"); + /* mt.getpeer = */ + lua_pushcfunction(L, stream_getpeer); + lua_setfield(L, -2, "getpeer"); /* mt.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: -- cgit v1.2.1