mod_auth_external: Add non-blocking mode (requires trunk, libevent and lpty 1.0.1). Our first complete non-blocking auth module!
--- a/mod_auth_external/mod_auth_external.lua Tue Aug 13 23:36:40 2013 +0100
+++ b/mod_auth_external/mod_auth_external.lua Tue Aug 13 23:37:31 2013 +0100
@@ -20,10 +20,25 @@
assert(not host:find(":"), "Invalid hostname");
local usermanager = require "core.usermanager";
local new_sasl = require "util.sasl".new;
+local server = require "net.server";
+local have_async, async = pcall(require, "util.async");
-local pty = lpty.new({ throw_errors = false, no_local_echo = true, use_path = false });
+local blocking = module:get_option_boolean("external_auth_blocking", not(have_async and server.event and lpty.getfd));
+
+if not blocking then
+ log("debug", "External auth in non-blocking mode, yay!")
+ waiter, guard = async.waiter, async.guarder();
+end
+
+local ptys = { lpty.new({ throw_errors = false, no_local_echo = true, use_path = false }) };
function send_query(text)
+ local pty = ptys[1];
+
+ local finished_with_pty
+ if not blocking then
+ finished_with_pty = guard(pty); -- Prevent others from crossing this line while we're busy
+ end
if not pty:hasproc() then
local status, ret = pty:exitstatus();
if status and (status ~= "exit" or ret ~= 0) then
@@ -39,7 +54,20 @@
end
pty:send(text);
- return pty:read(read_timeout);
+ if blocking then
+ return pty:read(read_timeout);
+ else
+ local response;
+ local wait, done = waiter();
+ server.addevent(pty:getfd(), server.event.EV_READ, function ()
+ response = pty:read();
+ done();
+ return -1;
+ end);
+ wait();
+ finished_with_pty();
+ return response;
+ end
end
function do_query(kind, username, password)