Merge 0.10->trunk
authorMatthew Wild <mwild1@gmail.com>
Sat, 2 Jan 2016 20:42:53 +0000 (20:42 +0000)
committerMatthew Wild <mwild1@gmail.com>
Sat, 2 Jan 2016 20:42:53 +0000 (20:42 +0000)
1  2 
net/server_event.lua
net/server_select.lua

diff --combined net/server_event.lua
index 9b1ffb2584288968b49a6b0a41db256ba008ada9,e5705ab5b792bc0045f929b298bb3660766ec686..677586645fd233b010ce82f66a169082d0a0ac86
@@@ -97,7 -97,7 +97,7 @@@ function interface_mt:_close(
        return self:_destroy();
  end
  
 -function interface_mt:_start_connection(plainssl) -- should be called from addclient
 +function interface_mt:_start_connection(plainssl) -- called from wrapclient
        local callback = function( event )
                if EV_TIMEOUT == event then  -- timeout during connection
                        self.fatalerror = "connection timeout"
@@@ -238,8 -238,8 +238,8 @@@ function interface_mt:_destroy()  -- cl
  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
 +              self.nointerface, self.noreading, self.nowriting = nointerface, noreading, nowriting
 +              return nointerface, noreading, nowriting
  end
  
  --TODO: Deprecate
@@@ -614,6 -614,7 +614,7 @@@ local function handleserver( server, ad
        local interface = {
                _connections = 0;
  
+               type = "server";
                conn = server;
                onconnect = listener.onconnect;  -- will be called when new client connected
                eventread = false;  -- read event handler
@@@ -701,14 -702,16 +702,14 @@@ local function addclient( addr, serverp
                debug "need luasec, but not available"
                return nil, "luasec not found"
        end
 -      if not typ then
 +      if getaddrinfo and not typ then
                local addrinfo, err = getaddrinfo(addr)
                if not addrinfo then return nil, err end
                if addrinfo[1] and addrinfo[1].family == "inet6" then
                        typ = "tcp6"
 -              else
 -                      typ = "tcp"
                end
        end
 -      local create = socket[typ]
 +      local create = socket[typ or "tcp"]
        if type( create ) ~= "function"  then
                return nil, "invalid socket type"
        end
        end
        client:settimeout( 0 )  -- set nonblocking
        local res, err = client:connect( addr, serverport )  -- connect
 -      if res or ( err == "timeout" ) then
 -              local ip, port = client:getsockname( )
 -              local interface = wrapclient( client, ip, serverport, listener, pattern, sslctx )
 -              interface:_start_connection( sslctx )
 +      if res or ( err == "timeout" or err == "Operation already in progress" ) then
 +              if client.getsockname then
 +                      addr = client:getsockname( )
 +              end
 +              local interface = wrapclient( client, addr, serverport, listener, pattern, sslctx )
                debug( "new connection id:", interface.id )
                return interface, err
        else
@@@ -739,7 -741,7 +740,7 @@@ en
  
  local function newevent( ... )
        return addevent( base, ... )
 -end
 +      end
  
  local function closeallservers ( arg )
        for item in pairs( interfacelist ) do
@@@ -751,9 -753,9 +752,9 @@@ en
  
  local function setquitting(yes)
        if yes then
 -              -- Quit now
 -              closeallservers();
 -              base:loopexit();
 +               -- Quit now
 +               closeallservers();
 +               base:loopexit();
        end
  end
  
@@@ -796,20 -798,6 +797,20 @@@ local function link(sender, receiver, b
        sender:set_mode("*a");
  end
  
 +local function add_task(delay, callback)
 +      local event_handle;
 +      event_handle = base:addevent(nil, 0, function ()
 +              local ret = callback(socket_gettime());
 +              if ret then
 +                      return 0, ret;
 +              elseif event_handle then
 +                      return -1;
 +              end
 +      end
 +      , delay);
 +      return event_handle;
 +end
 +
  return {
        cfg = cfg,
        base = base,
        closeall = closeallservers,
        get_backend = get_backend,
        hook_signal = hook_signal,
 +      add_task = add_task,
  
        __NAME = SCRIPT_NAME,
        __DATE = LAST_MODIFIED,
diff --combined net/server_select.lua
index 35dcb5a75cc336de133cc043d772e400ae3c1a61,87921df4badc579d21fa70b83cd92af02ac6f414..ced73074d56f981357eb6b3513df3949825b8942
@@@ -31,16 -31,17 +31,16 @@@ local tostring = use "tostring
  
  --// lua libs //--
  
 -local os = use "os"
  local table = use "table"
  local string = use "string"
  local coroutine = use "coroutine"
  
  --// lua lib methods //--
  
 -local os_difftime = os.difftime
  local math_min = math.min
  local math_huge = math.huge
  local table_concat = table.concat
 +local table_insert = table.insert
  local string_sub = string.sub
  local coroutine_wrap = coroutine.wrap
  local coroutine_yield = coroutine.yield
@@@ -56,6 -57,7 +56,6 @@@ local getaddrinfo = luasocket.dns.getad
  
  local ssl_wrap = ( has_luasec and luasec.wrap )
  local socket_bind = luasocket.bind
 -local socket_sleep = luasocket.sleep
  local socket_select = luasocket.select
  
  --// functions //--
@@@ -99,6 -101,7 +99,6 @@@ local _sendtraffi
  local _readtraffic
  
  local _selecttimeout
 -local _sleeptime
  local _tcpbacklog
  
  local _starttime
@@@ -111,6 -114,8 +111,6 @@@ local _checkinterva
  local _sendtimeout
  local _readtimeout
  
 -local _timer
 -
  local _maxselectlen
  local _maxfd
  
@@@ -135,6 -140,7 +135,6 @@@ _sendtraffic = 0 -- some stat
  _readtraffic = 0
  
  _selecttimeout = 1 -- timeout of socket.select
 -_sleeptime = 0 -- time to wait at the end of every loop
  _tcpbacklog = 128 -- some kind of hint to the OS
  
  _maxsendlen = 51000 * 1024 -- max len of send buffer
@@@ -286,6 -292,7 +286,6 @@@ wrapconnection = function( server, list
        local bufferqueuelen = 0        -- end of buffer array
  
        local toclose
 -      local fatalerror
        local needtls
  
        local bufferlen = 0
                        return dispatch( handler, buffer, err )
                else    -- connections was closed or fatal error
                        out_put( "server.lua: client ", tostring(ip), ":", tostring(clientport), " read error: ", tostring(err) )
 -                      fatalerror = true
                        _ = handler and handler:force_close( err )
                        return false
                end
                        return true
                else    -- connection was closed during sending or fatal error
                        out_put( "server.lua: client ", tostring(ip), ":", tostring(clientport), " write error: ", tostring(err) )
 -                      fatalerror = true
                        _ = handler and handler:force_close( err )
                        return false
                end
@@@ -783,6 -792,7 +783,6 @@@ en
  getsettings = function( )
        return {
                select_timeout = _selecttimeout;
 -              select_sleep_time = _sleeptime;
                tcp_backlog = _tcpbacklog;
                max_send_buffer_size = _maxsendlen;
                max_receive_buffer_size = _maxreadlen;
@@@ -800,6 -810,7 +800,6 @@@ changesettings = function( new 
                return nil, "invalid settings table"
        end
        _selecttimeout = tonumber( new.select_timeout ) or _selecttimeout
 -      _sleeptime = tonumber( new.select_sleep_time ) or _sleeptime
        _maxsendlen = tonumber( new.max_send_buffer_size ) or _maxsendlen
        _maxreadlen = tonumber( new.max_receive_buffer_size ) or _maxreadlen
        _checkinterval = tonumber( new.select_idle_check_interval ) or _checkinterval
@@@ -821,49 -832,6 +821,49 @@@ addtimer = function( listener 
        return true
  end
  
 +local add_task do
 +      local data = {};
 +      local new_data = {};
 +
 +      function add_task(delay, callback)
 +              local current_time = luasocket_gettime();
 +              delay = delay + current_time;
 +              if delay >= current_time then
 +                      table_insert(new_data, {delay, callback});
 +              else
 +                      local r = callback(current_time);
 +                      if r and type(r) == "number" then
 +                              return add_task(r, callback);
 +                      end
 +              end
 +      end
 +
 +      addtimer(function(current_time)
 +              if #new_data > 0 then
 +                      for _, d in pairs(new_data) do
 +                              table_insert(data, d);
 +                      end
 +                      new_data = {};
 +              end
 +
 +              local next_time = math_huge;
 +              for i, d in pairs(data) do
 +                      local t, callback = d[1], d[2];
 +                      if t <= current_time then
 +                              data[i] = nil;
 +                              local r = callback(current_time);
 +                              if type(r) == "number" then
 +                                      add_task(r, callback);
 +                                      next_time = math_min(next_time, r);
 +                              end
 +                      else
 +                              next_time = math_min(next_time, t - current_time);
 +                      end
 +              end
 +              return next_time;
 +      end);
 +end
 +
  stats = function( )
        return _readtraffic, _sendtraffic, _readlistlen, _sendlistlen, _timerlistlen
  end
@@@ -877,15 -845,8 +877,15 @@@ en
  loop = function(once) -- this is the main loop of the program
        if quitting then return "quitting"; end
        if once then quitting = "once"; end
 -      local next_timer_time = math_huge;
 +      _currenttime = luasocket_gettime( )
        repeat
 +              -- Fire timers
 +              local next_timer_time = math_huge;
 +              for i = 1, _timerlistlen do
 +                      local t = _timerlist[ i ]( _currenttime ) -- fire timers
 +                      if t then next_timer_time = math_min(next_timer_time, t); end
 +              end
 +
                local read, write, err = socket_select( _readlist, _sendlist, math_min(_selecttimeout, next_timer_time) )
                for i, socket in ipairs( write ) do -- send data waiting in writequeues
                        local handler = _socketlist[ socket ]
                _currenttime = luasocket_gettime( )
  
                -- Check for socket timeouts
 -              local difftime = os_difftime( _currenttime - _starttime )
 -              if difftime > _checkinterval then
 +              if _currenttime - _starttime > _checkinterval then
                        _starttime = _currenttime
                        for handler, timestamp in pairs( _writetimes ) do
 -                              if os_difftime( _currenttime - timestamp ) > _sendtimeout then
 +                              if _currenttime - timestamp > _sendtimeout then
                                        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
 +                              if _currenttime - timestamp > _readtimeout then
                                        if not(handler.onreadtimeout) or handler:onreadtimeout() ~= true then
                                                handler.disconnect( )( handler, "read timeout" )
                                                handler:close( )        -- forced disconnect?
                                end
                        end
                end
 -
 -              -- Fire timers
 -              if _currenttime - _timer >= math_min(next_timer_time, 1) then
 -                      next_timer_time = math_huge;
 -                      for i = 1, _timerlistlen do
 -                              local t = _timerlist[ i ]( _currenttime ) -- fire timers
 -                              if t then next_timer_time = math_min(next_timer_time, t); end
 -                      end
 -                      _timer = _currenttime
 -              else
 -                      next_timer_time = next_timer_time - (_currenttime - _timer);
 -              end
 -
 -              -- wait some time (0 by default)
 -              socket_sleep( _sleeptime )
        until quitting;
        if once and quitting == "once" then quitting = nil; return; end
+       closeall();
        return "quitting"
  end
  
@@@ -977,14 -955,16 +978,14 @@@ local addclient = function( address, po
        elseif sslctx and not has_luasec then
                err = "luasec not found"
        end
 -      if not typ then
 +      if getaddrinfo and not typ then
                local addrinfo, err = getaddrinfo(address)
                if not addrinfo then return nil, err end
                if addrinfo[1] and addrinfo[1].family == "inet6" then
                        typ = "tcp6"
 -              else
 -                      typ = "tcp"
                end
        end
 -      local create = luasocket[typ]
 +      local create = luasocket[typ or "tcp"]
        if type( create ) ~= "function"  then
                err = "invalid socket type"
        end
        end
        client:settimeout( 0 )
        local ok, err = client:connect( address, port )
 -      if ok or err == "timeout" then
 +      if ok or err == "timeout" or err == "Operation already in progress" then
                return wrapclient( client, address, port, listeners, pattern, sslctx )
        else
                return nil, err
        end
  end
  
 ---// EXPERIMENTAL //--
 -
  ----------------------------------// BEGIN //--
  
  use "setmetatable" ( _socketlist, { __mode = "k" } )
  use "setmetatable" ( _readtimes, { __mode = "k" } )
  use "setmetatable" ( _writetimes, { __mode = "k" } )
  
 -_timer = luasocket_gettime( )
  _starttime = luasocket_gettime( )
  
  local function setlogger(new_logger)
@@@ -1027,7 -1010,6 +1028,7 @@@ en
  
  return {
        _addtimer = addtimer,
 +      add_task = add_task;
  
        addclient = addclient,
        wrapclient = wrapclient,