aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/adns.lua6
-rw-r--r--net/dns.lua25
-rw-r--r--net/http.lua30
-rw-r--r--net/http/server.lua27
-rw-r--r--net/server.lua2
-rw-r--r--net/server_event.lua157
-rw-r--r--net/server_select.lua28
7 files changed, 148 insertions, 127 deletions
diff --git a/net/adns.lua b/net/adns.lua
index 2a3fa8ad..15814fe7 100644
--- a/net/adns.lua
+++ b/net/adns.lua
@@ -1,7 +1,7 @@
-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
---
+--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
@@ -65,7 +65,7 @@ function new_async_socket(sock, resolver)
if resolver.socketset[conn] == resolver.best_server and resolver.best_server == #servers then
log("error", "Exhausted all %d configured DNS servers, next lookup will try %s again", #servers, servers[1]);
end
-
+
resolver:servfail(conn); -- Let the magic commence
end
end
@@ -73,7 +73,7 @@ function new_async_socket(sock, resolver)
if not handler then
return nil, err;
end
-
+
handler.settimeout = function () end
handler.setsockname = function (_, ...) return sock:setsockname(...); end
handler.setpeername = function (_, ...) peername = (...); local ret = sock:setpeername(...); _:set_send(dummy_send); return ret; end
diff --git a/net/dns.lua b/net/dns.lua
index 492bd1c5..088067ae 100644
--- a/net/dns.lua
+++ b/net/dns.lua
@@ -14,6 +14,7 @@
local socket = require "socket";
local timer = require "util.timer";
+local new_ip = require "util.ip".new_ip;
local _, windows = pcall(require, "util.windows");
local is_windows = (_ and windows) or os.getenv("WINDIR");
@@ -597,11 +598,12 @@ function resolver:adddefaultnameservers() -- - - - - adddefaultnameservers
if resolv_conf then
for line in resolv_conf:lines() do
line = line:gsub("#.*$", "")
- :match('^%s*nameserver%s+(.*)%s*$');
+ :match('^%s*nameserver%s+([%x:%.]*)%s*$');
if line then
- line:gsub("%f[%d.](%d+%.%d+%.%d+%.%d+)%f[^%d.]", function (address)
- self:addnameserver(address)
- end);
+ local ip = new_ip(line);
+ if ip then
+ self:addnameserver(ip.addr);
+ end
end
end
end
@@ -621,7 +623,12 @@ function resolver:getsocket(servernum) -- - - - - - - - - - - - - getsocket
if sock then return sock; end
local err;
- sock, err = socket.udp();
+ local peer = self.server[servernum];
+ if peer:find(":") then
+ sock, err = socket.udp6();
+ else
+ sock, err = socket.udp();
+ end
if sock and self.socket_wrapper then sock, err = self.socket_wrapper(sock, self); end
if not sock then
return nil, err;
@@ -629,7 +636,7 @@ function resolver:getsocket(servernum) -- - - - - - - - - - - - - getsocket
sock:settimeout(0);
-- todo: attempt to use a random port, fallback to 0
sock:setsockname('*', 0);
- sock:setpeername(self.server[servernum], 53);
+ sock:setpeername(peer, 53);
self.socket[servernum] = sock;
self.socketset[sock] = servernum;
return sock;
@@ -753,7 +760,7 @@ function resolver:query(qname, qtype, qclass) -- - - - - - - - - - -- query
return nil, err;
end
conn:send (o.packet)
-
+
if timer and self.timeout then
local num_servers = #self.server;
local i = 1;
@@ -849,7 +856,7 @@ function resolver:receive(rset) -- - - - - - - - - - - - - - - - - receive
-- retire the query
local queries = self.active[response.header.id];
queries[response.question.raw] = nil;
-
+
if not next(queries) then self.active[response.header.id] = nil; end
if not next(self.active) then self:closeall(); end
@@ -864,7 +871,7 @@ function resolver:receive(rset) -- - - - - - - - - - - - - - - - - receive
set(self.wanted, q.class, q.type, q.name, nil);
end
end
-
+
end
end
end
diff --git a/net/http.lua b/net/http.lua
index 6ddb1900..ab9ec7b6 100644
--- a/net/http.lua
+++ b/net/http.lua
@@ -1,7 +1,7 @@
-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
---
+--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
@@ -37,7 +37,7 @@ function listener.onconnect(conn)
if req.query then
t_insert(request_line, 4, "?"..req.query);
end
-
+
conn:write(t_concat(request_line));
local t = { [2] = ": ", [4] = "\r\n" };
for k, v in pairs(req.headers) do
@@ -45,7 +45,7 @@ function listener.onconnect(conn)
conn:write(t_concat(t));
end
conn:write("\r\n");
-
+
if req.body then
conn:write(req.body);
end
@@ -81,12 +81,12 @@ local function request_reader(request, data, err)
end
destroy_request(request);
end
-
+
if not data then
error_cb(err);
return;
end
-
+
local function success_cb(r)
if request.callback then
request.callback(r.body, r.code, r, request);
@@ -105,18 +105,18 @@ end
local function handleerr(err) log("error", "Traceback[http]: %s", traceback(tostring(err), 2)); end
function request(u, ex, callback)
local req = url.parse(u);
-
+
if not (req and req.host) then
callback(nil, 0, req);
return nil, "invalid-url";
end
-
+
if not req.path then
req.path = "/";
end
-
+
local method, headers, body;
-
+
local host, port = req.host, req.port;
local host_header = host;
if (port == "80" and req.scheme == "http")
@@ -130,7 +130,7 @@ function request(u, ex, callback)
["Host"] = host_header;
["User-Agent"] = "Prosody XMPP Server";
};
-
+
if req.userinfo then
headers["Authorization"] = "Basic "..b64(req.userinfo);
end
@@ -150,16 +150,16 @@ function request(u, ex, callback)
end
end
end
-
+
-- Attach to request object
req.method, req.headers, req.body = method, headers, body;
-
+
local using_https = req.scheme == "https";
if using_https and not ssl_available then
error("SSL not available, unable to contact https URL");
end
local port_number = port and tonumber(port) or (using_https and 443 or 80);
-
+
-- Connect the socket, and wrap it with net.server
local conn = socket.tcp();
conn:settimeout(10);
@@ -168,7 +168,7 @@ function request(u, ex, callback)
callback(nil, 0, req);
return nil, err;
end
-
+
local sslctx = false;
if using_https then
sslctx = ex and ex.sslctx or { mode = "client", protocol = "sslv23", options = { "no_sslv2" } };
@@ -176,7 +176,7 @@ function request(u, ex, callback)
req.handler, req.conn = assert(server.wrapclient(conn, host, port_number, listener, "*a", sslctx));
req.write = function (...) return req.handler:write(...); end
-
+
req.callback = function (content, code, request, response) log("debug", "Calling callback, status %s", code or "---"); return select(2, xpcall(function () return callback(content, code, request, response) end, handleerr)); end
req.reader = request_reader;
req.state = "status";
diff --git a/net/http/server.lua b/net/http/server.lua
index 0f379e96..510b77fb 100644
--- a/net/http/server.lua
+++ b/net/http/server.lua
@@ -185,6 +185,7 @@ function handle_request(conn, request, finish_cb)
persistent = persistent;
conn = conn;
send = _M.send_response;
+ done = _M.finish_response;
finish_cb = finish_cb;
};
conn._http_open_response = response;
@@ -204,7 +205,7 @@ function handle_request(conn, request, finish_cb)
err_code, err = 400, "Missing or invalid 'Host' header";
end
end
-
+
if err then
response.status_code = err_code;
response:send(events.fire_event("http-error", { code = err_code, message = err }));
@@ -246,24 +247,30 @@ function handle_request(conn, request, finish_cb)
response.status_code = 404;
response:send(events.fire_event("http-error", { code = 404 }));
end
-function _M.send_response(response, body)
- if response.finished then return; end
- response.finished = true;
- response.conn._http_open_response = nil;
-
+local function prepare_header(response)
local status_line = "HTTP/"..response.request.httpversion.." "..(response.status or codes[response.status_code]);
local headers = response.headers;
- body = body or response.body or "";
- headers.content_length = #body;
-
local output = { status_line };
for k,v in pairs(headers) do
t_insert(output, headerfix[k]..v);
end
t_insert(output, "\r\n\r\n");
+ return output;
+end
+_M.prepare_header = prepare_header;
+function _M.send_response(response, body)
+ if response.finished then return; end
+ body = body or response.body or "";
+ response.headers.content_length = #body;
+ local output = prepare_header(response);
t_insert(output, body);
-
response.conn:write(t_concat(output));
+ response:done();
+end
+function _M.finish_response(response)
+ if response.finished then return; end
+ response.finished = true;
+ response.conn._http_open_response = nil;
if response.on_destroy then
response:on_destroy();
response.on_destroy = nil;
diff --git a/net/server.lua b/net/server.lua
index 375e7081..2a0b89ae 100644
--- a/net/server.lua
+++ b/net/server.lua
@@ -1,7 +1,7 @@
-- Prosody IM
-- Copyright (C) 2008-2010 Matthew Wild
-- Copyright (C) 2008-2010 Waqas Hussain
---
+--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
diff --git a/net/server_event.lua b/net/server_event.lua
index 25799640..53330997 100644
--- a/net/server_event.lua
+++ b/net/server_event.lua
@@ -115,10 +115,10 @@ end )( )
local interface_mt
do
interface_mt = {}; interface_mt.__index = interface_mt;
-
+
local addevent = base.addevent
local coroutine_wrap, coroutine_yield = coroutine.wrap,coroutine.yield
-
+
-- Private methods
function interface_mt:_position(new_position)
self.position = new_position or self.position
@@ -127,7 +127,7 @@ do
function interface_mt:_close()
return self:_destroy();
end
-
+
function interface_mt:_start_connection(plainssl) -- should be called from addclient
local callback = function( event )
if EV_TIMEOUT == event then -- timeout during connection
@@ -268,12 +268,12 @@ do
interfacelist( "delete", self )
return true
end
-
+
function interface_mt:_lock(nointerface, noreading, nowriting) -- lock or unlock this interface or events
self.nointerface, self.noreading, self.nowriting = nointerface, noreading, nowriting
return nointerface, noreading, nowriting
end
-
+
--TODO: Deprecate
function interface_mt:lock_read(switch)
if switch then
@@ -300,7 +300,7 @@ do
end
return self._connections
end
-
+
-- Public methods
function interface_mt:write(data)
if self.nowriting then return nil, "locked" end
@@ -343,27 +343,27 @@ do
return true
end
end
-
+
function interface_mt:socket()
return self.conn
end
-
+
function interface_mt:server()
return self._server or self;
end
-
+
function interface_mt:port()
return self._port
end
-
+
function interface_mt:serverport()
return self._serverport
end
-
+
function interface_mt:ip()
return self._ip
end
-
+
function interface_mt:ssl()
return self._usingssl
end
@@ -372,15 +372,15 @@ do
function interface_mt:type()
return self._type or "client"
end
-
+
function interface_mt:connections()
return self._connections
end
-
+
function interface_mt:address()
return self.addr
end
-
+
function interface_mt:set_sslctx(sslctx)
self._sslctx = sslctx;
if sslctx then
@@ -396,11 +396,11 @@ do
end
return self._pattern;
end
-
+
function interface_mt:set_send(new_send)
-- No-op, we always use the underlying connection's send
end
-
+
function interface_mt:starttls(sslctx, call_onconnect)
debug( "try to start ssl at client id:", self.id )
local err
@@ -429,19 +429,20 @@ do
self.starttls = false;
return true
end
-
+
function interface_mt:setoption(option, value)
if self.conn.setoption then
return self.conn:setoption(option, value);
end
return false, "setoption not implemented";
end
-
+
function interface_mt:setlistener(listener)
- self.onconnect, self.ondisconnect, self.onincoming, self.ontimeout, self.onstatus
- = listener.onconnect, listener.ondisconnect, listener.onincoming, listener.ontimeout, listener.onstatus;
+ self.onconnect, self.ondisconnect, self.onincoming, self.ontimeout, self.onreadtimeout, self.onstatus
+ = listener.onconnect, listener.ondisconnect, listener.onincoming,
+ listener.ontimeout, listener.onreadtimeout, listener.onstatus;
end
-
+
-- Stub handlers
function interface_mt:onconnect()
end
@@ -451,6 +452,12 @@ do
end
function interface_mt:ontimeout()
end
+ function interface_mt:onreadtimeout()
+ self.fatalerror = "timeout during receiving"
+ debug( "connection failed:", self.fatalerror )
+ self:_close()
+ self.eventread = nil
+ end
function interface_mt:ondrain()
end
function interface_mt:onstatus()
@@ -478,6 +485,7 @@ do
ondisconnect = listener.ondisconnect; -- will be called when client disconnects
onincoming = listener.onincoming; -- will be called when client sends data
ontimeout = listener.ontimeout; -- called when fatal socket timeout occurs
+ onreadtimeout = listener.onreadtimeout; -- called when socket inactivity timeout occurs
ondrain = listener.ondrain; -- called when writebuffer is empty
onstatus = listener.onstatus; -- called for status changes (e.g. of SSL/TLS)
eventread = false, eventwrite = false, eventclose = false,
@@ -492,7 +500,7 @@ do
noreading = false, nowriting = false; -- locks of the read/writecallback
startsslcallback = false; -- starting handshake callback
position = false; -- position of client in interfacelist
-
+
-- Properties
_ip = ip, _port = port, _server = server, _pattern = pattern,
_serverport = (server and server:port() or nil),
@@ -568,7 +576,7 @@ do
end
end
end
-
+
interface.readcallback = function( event ) -- called on read events
--vdebug( "new client read event, id/ip/port:", tostring(interface.id), tostring(ip), tostring(port) )
if interface.noreading or interface.fatalerror then -- leave this event
@@ -576,61 +584,56 @@ do
interface.eventread = nil
return -1
end
- if EV_TIMEOUT == event then -- took too long to get some data from client -> disconnect
- interface.fatalerror = "timeout during receiving"
- debug( "connection failed:", interface.fatalerror )
+ if EV_TIMEOUT == event and interface:onreadtimeout() ~= true then
+ return -1 -- took too long to get some data from client -> disconnect
+ end
+ if interface._usingssl then -- handle luasec
+ if interface.eventwritetimeout then -- ok, in the past writecallback was regged
+ local ret = interface.writecallback( ) -- call it
+ --vdebug( "tried to write in readcallback, result:", tostring(ret) )
+ end
+ if interface.eventreadtimeout then
+ interface.eventreadtimeout:close( )
+ interface.eventreadtimeout = nil
+ end
+ end
+ local buffer, err, part = interface.conn:receive( interface._pattern ) -- receive buffer with "pattern"
+ --vdebug( "read data:", tostring(buffer), "error:", tostring(err), "part:", tostring(part) )
+ buffer = buffer or part
+ if buffer and #buffer > cfg.MAX_READ_LENGTH then -- check buffer length
+ interface.fatalerror = "receive buffer exceeded"
+ debug( "fatal error:", interface.fatalerror )
interface:_close()
interface.eventread = nil
return -1
- else -- can read
- if interface._usingssl then -- handle luasec
- if interface.eventwritetimeout then -- ok, in the past writecallback was regged
- local ret = interface.writecallback( ) -- call it
- --vdebug( "tried to write in readcallback, result:", tostring(ret) )
- end
- if interface.eventreadtimeout then
- interface.eventreadtimeout:close( )
- interface.eventreadtimeout = nil
+ end
+ if err and ( err ~= "timeout" and err ~= "wantread" ) then
+ if "wantwrite" == err then -- need to read on write event
+ if not interface.eventwrite then -- register new write event if needed
+ interface.eventwrite = addevent( base, interface.conn, EV_WRITE, interface.writecallback, cfg.WRITE_TIMEOUT )
end
- end
- local buffer, err, part = interface.conn:receive( interface._pattern ) -- receive buffer with "pattern"
- --vdebug( "read data:", tostring(buffer), "error:", tostring(err), "part:", tostring(part) )
- buffer = buffer or part
- if buffer and #buffer > cfg.MAX_READ_LENGTH then -- check buffer length
- interface.fatalerror = "receive buffer exceeded"
- debug( "fatal error:", interface.fatalerror )
+ interface.eventreadtimeout = addevent( base, nil, EV_TIMEOUT,
+ function( )
+ interface:_close()
+ end, cfg.READ_TIMEOUT
+ )
+ debug( "wantwrite during read attempt, reg it in writecallback but dont know what really happens next..." )
+ -- to be honest i dont know what happens next, if it is allowed to first read, the write etc...
+ else -- connection was closed or fatal error
+ interface.fatalerror = err
+ debug( "connection failed in read event:", interface.fatalerror )
interface:_close()
interface.eventread = nil
return -1
end
- if err and ( err ~= "timeout" and err ~= "wantread" ) then
- if "wantwrite" == err then -- need to read on write event
- if not interface.eventwrite then -- register new write event if needed
- interface.eventwrite = addevent( base, interface.conn, EV_WRITE, interface.writecallback, cfg.WRITE_TIMEOUT )
- end
- interface.eventreadtimeout = addevent( base, nil, EV_TIMEOUT,
- function( )
- interface:_close()
- end, cfg.READ_TIMEOUT
- )
- debug( "wantwrite during read attempt, reg it in writecallback but dont know what really happens next..." )
- -- to be honest i dont know what happens next, if it is allowed to first read, the write etc...
- else -- connection was closed or fatal error
- interface.fatalerror = err
- debug( "connection failed in read event:", interface.fatalerror )
- interface:_close()
- interface.eventread = nil
- return -1
- end
- else
- interface.onincoming( interface, buffer, err ) -- send new data to listener
- end
- if interface.noreading then
- interface.eventread = nil;
- return -1;
- end
- return EV_READ, cfg.READ_TIMEOUT
+ else
+ interface.onincoming( interface, buffer, err ) -- send new data to listener
end
+ if interface.noreading then
+ interface.eventread = nil;
+ return -1;
+ end
+ return EV_READ, cfg.READ_TIMEOUT
end
client:settimeout( 0 ) -- set non blocking
@@ -646,7 +649,7 @@ do
debug "creating server interface..."
local interface = {
_connections = 0;
-
+
conn = server;
onconnect = listener.onconnect; -- will be called when new client connected
eventread = false; -- read event handler
@@ -654,7 +657,7 @@ do
readcallback = false; -- read event callback
fatalerror = false; -- error message
nointerface = true; -- lock/unlock parameter
-
+
_ip = addr, _port = port, _pattern = pattern,
_sslctx = sslctx;
}
@@ -693,12 +696,12 @@ do
clientinterface:_start_session( true )
end
debug( "accepted incoming client connection from:", client_ip or "<unknown IP>", client_port or "<unknown port>", "to", port or "<unknown port>");
-
+
client, err = server:accept() -- try to accept again
end
return EV_READ
end
-
+
server:settimeout( 0 )
setmetatable(interface, interface_mt)
interfacelist( "add", interface )
@@ -741,7 +744,7 @@ do
return interface, client
--function handleclient( client, ip, port, server, pattern, listener, _, sslctx ) -- creates an client interface
end
-
+
function addclient( addr, serverport, listener, pattern, localaddr, localport, sslcfg, startssl )
local client, err = socket.tcp() -- creating new socket
if not client then
@@ -832,14 +835,14 @@ end
local function link(sender, receiver, buffersize)
local sender_locked;
-
+
function receiver:ondrain()
if sender_locked then
sender:resume();
sender_locked = nil;
end
end
-
+
function sender:onincoming(data)
receiver:write(data);
if receiver.writebufferlen >= buffersize then
diff --git a/net/server_select.lua b/net/server_select.lua
index 4bda3ef0..daad0f50 100644
--- a/net/server_select.lua
+++ b/net/server_select.lua
@@ -1,7 +1,7 @@
---
+--
-- server.lua by blastbeat of the luadch project
-- Re-used here under the MIT/X Consortium License
---
+--
-- Modifications (C) 2008-2010 Matthew Wild, Waqas Hussain
--
@@ -145,7 +145,7 @@ _tcpbacklog = 128 -- some kind of hint to the OS
_maxsendlen = 51000 * 1024 -- max len of send buffer
_maxreadlen = 25000 * 1024 -- max len of read buffer
-_checkinterval = 1200000 -- interval in secs to check idle clients
+_checkinterval = 30 -- interval in secs to check idle clients
_sendtimeout = 60000 -- allowed send idle time in secs
_readtimeout = 6 * 60 * 60 -- allowed read idle time in secs
@@ -284,6 +284,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport
local status = listeners.onstatus
local disconnect = listeners.ondisconnect
local drain = listeners.ondrain
+ local onreadtimeout = listeners.onreadtimeout;
local bufferqueue = { } -- buffer array
local bufferqueuelen = 0 -- end of buffer array
@@ -312,11 +313,14 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport
handler.disconnect = function( )
return disconnect
end
+ handler.onreadtimeout = onreadtimeout;
+
handler.setlistener = function( self, listeners )
dispatch = listeners.onincoming
disconnect = listeners.ondisconnect
status = listeners.onstatus
drain = listeners.ondrain
+ handler.onreadtimeout = listeners.onreadtimeout
end
handler.getstats = function( )
return readtraffic, sendtraffic
@@ -608,7 +612,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport
shutdown = id
_socketlist[ socket ] = handler
_readlistlen = addsocket(_readlist, socket, _readlistlen)
-
+
-- remove traces of the old socket
_readlistlen = removesocket( _readlist, oldsocket, _readlistlen )
_sendlistlen = removesocket( _sendlist, oldsocket, _sendlistlen )
@@ -696,7 +700,7 @@ local function link(sender, receiver, buffersize)
sender_locked = nil;
end
end
-
+
local _readbuffer = sender.readbuffer;
function sender.readbuffer()
_readbuffer();
@@ -864,16 +868,16 @@ loop = function(once) -- this is the main loop of the program
_starttime = _currenttime
for handler, timestamp in pairs( _writetimes ) do
if os_difftime( _currenttime - timestamp ) > _sendtimeout then
- --_writetimes[ handler ] = nil
handler.disconnect( )( handler, "send timeout" )
handler:force_close() -- forced disconnect
end
end
for handler, timestamp in pairs( _readtimes ) do
if os_difftime( _currenttime - timestamp ) > _readtimeout then
- --_readtimes[ handler ] = nil
- handler.disconnect( )( handler, "read timeout" )
- handler:close( ) -- forced disconnect?
+ if not(handler.onreadtimeout) or handler:onreadtimeout() ~= true then
+ handler.disconnect( )( handler, "read timeout" )
+ handler:close( ) -- forced disconnect?
+ end
end
end
end
@@ -934,9 +938,9 @@ local addclient = function( address, port, listeners, pattern, sslctx )
client:settimeout( 0 )
_, err = client:connect( address, port )
if err then -- try again
- local handler = wrapclient( client, address, port, listeners )
+ return wrapclient( client, address, port, listeners, pattern, sslctx )
else
- wrapconnection( nil, listeners, client, address, port, "clientport", pattern, sslctx )
+ return wrapconnection( nil, listeners, client, address, port, "clientport", pattern, sslctx )
end
end
@@ -966,7 +970,7 @@ return {
addclient = addclient,
wrapclient = wrapclient,
-
+
loop = loop,
link = link,
step = step,