Merge 0.10->trunk
authorKim Alvefur <zash@zash.se>
Wed, 2 Mar 2016 15:34:34 +0000 (16:34 +0100)
committerKim Alvefur <zash@zash.se>
Wed, 2 Mar 2016 15:34:34 +0000 (16:34 +0100)
1  2 
net/server_event.lua

index 677586645fd233b010ce82f66a169082d0a0ac86,70a6dc37881af22fd246201c959ae486b2c84642..7940a1b831e1c4c11c0dcd6a9dc66af5e5db2260
@@@ -196,217 -153,261 +196,218 @@@ function interface_mt:_start_ssl(call_o
                                        self.ondisconnect = nil  -- dont call this when client isnt really connected
                                end
                                self:_close()
 -                              debug( "fatal error while ssl wrapping:", err )
 -                              return false
 +                              debug( "handshake failed because:", self.fatalerror )
 +                              self.eventhandshake = nil
 +                              return -1
                        end
 -                      self.conn:settimeout( 0 )  -- set non blocking
 -      local handshakecallback = coroutine_wrap(function( event )
 -                                      local _, err
 -                                      local attempt = 0
 -                                      local maxattempt = cfg.MAX_HANDSHAKE_ATTEMPTS
 -                                      while attempt < maxattempt do  -- no endless loop
 -                                              attempt = attempt + 1
 -                                              debug( "ssl handshake of client with id:"..tostring(self)..", attempt:"..attempt )
 -                                              if attempt > maxattempt then
 -                                                      self.fatalerror = "max handshake attempts exceeded"
 -                                              elseif EV_TIMEOUT == event then
 -                                                      self.fatalerror = "timeout during handshake"
 -                                              else
 -                                                      _, err = self.conn:dohandshake( )
 -                                                      if not err then
 -                                                              self:_lock( false, false, false )  -- unlock the interface; sending, closing etc allowed
 -                                                              self.send = self.conn.send  -- caching table lookups with new client object
 -                                                              self.receive = self.conn.receive
 -                                                              if not call_onconnect then  -- trigger listener
 -                                                                      self:onstatus("ssl-handshake-complete");
 -                                                              end
 -                                                              self:_start_session( call_onconnect )
 -                                                              debug( "ssl handshake done" )
 -                                                              self.eventhandshake = nil
 -                                                              return -1
 -                                                      end
 -                                                      if err == "wantwrite" then
 -                                                              event = EV_WRITE
 -                                                      elseif err == "wantread" then
 -                                                              event = EV_READ
 -                                                      else
 -                                                              debug( "ssl handshake error:", err )
 -                                                              self.fatalerror = err
 -                                                      end
 -                                              end
 -                                              if self.fatalerror then
 -                                                      if call_onconnect then
 -                                                              self.ondisconnect = nil  -- dont call this when client isnt really connected
 -                                                      end
 -                                                      self:_close()
 -                                                      debug( "handshake failed because:", self.fatalerror )
 -                                                      self.eventhandshake = nil
 -                                                      return -1
 -                                              end
 -                                              event = coroutine_yield( event, cfg.HANDSHAKE_TIMEOUT )  -- yield this monster...
 -                                      end
 -                              end
 -                      )
 -                      debug "starting handshake..."
 -                      self:_lock( false, true, true )  -- unlock read/write events, but keep interface locked
 -                      self.eventhandshake = addevent( base, self.conn, EV_READWRITE, handshakecallback, cfg.HANDSHAKE_TIMEOUT )
 -                      return true
 +                      event = coroutine_yield( event, cfg.HANDSHAKE_TIMEOUT )  -- yield this monster...
 +              end
        end
 -      function interface_mt:_destroy()  -- close this interface + events and call last listener
 -                      debug( "closing client with id:", self.id, self.fatalerror )
 -                      self:_lock( true, true, true )  -- first of all, lock the interface to avoid further actions
 -                      local _
 -                      _ = self.eventread and self.eventread:close( )
 -                      if self.type == "client" then
 -                              _ = self.eventwrite and self.eventwrite:close( )
 -                              _ = self.eventhandshake and self.eventhandshake:close( )
 -                              _ = self.eventstarthandshake and self.eventstarthandshake:close( )
 -                              _ = self.eventconnect and self.eventconnect:close( )
 -                              _ = self.eventsession and self.eventsession:close( )
 -                              _ = self.eventwritetimeout and self.eventwritetimeout:close( )
 -                              _ = self.eventreadtimeout and self.eventreadtimeout:close( )
 -                              _ = self.ondisconnect and self:ondisconnect( self.fatalerror ~= "client to close" and self.fatalerror)  -- call ondisconnect listener (wont be the case if handshake failed on connect)
 -                              _ = self.conn and self.conn:close( ) -- close connection
 -                              _ = self._server and self._server:counter(-1);
 -                              self.eventread, self.eventwrite = nil, nil
 -                              self.eventstarthandshake, self.eventhandshake, self.eventclose = nil, nil, nil
 -                              self.readcallback, self.writecallback = nil, nil
 -                      else
 -                              self.conn:close( )
 -                              self.eventread, self.eventclose = nil, nil
 -                              self.interface, self.readcallback = nil, nil
 -                      end
 -      interfacelist[ self ] = nil
 -                      return true
 +      )
 +      debug "starting handshake..."
 +      self:_lock( false, true, true )  -- unlock read/write events, but keep interface locked
 +      self.eventhandshake = addevent( base, self.conn, EV_READWRITE, handshakecallback, cfg.HANDSHAKE_TIMEOUT )
 +      return true
 +end
 +function interface_mt:_destroy()  -- close this interface + events and call last listener
 +      debug( "closing client with id:", self.id, self.fatalerror )
 +      self:_lock( true, true, true )  -- first of all, lock the interface to avoid further actions
 +      local _
 +      _ = self.eventread and self.eventread:close( )
 +      if self.type == "client" then
 +              _ = self.eventwrite and self.eventwrite:close( )
 +              _ = self.eventhandshake and self.eventhandshake:close( )
 +              _ = self.eventstarthandshake and self.eventstarthandshake:close( )
 +              _ = self.eventconnect and self.eventconnect:close( )
 +              _ = self.eventsession and self.eventsession:close( )
 +              _ = self.eventwritetimeout and self.eventwritetimeout:close( )
 +              _ = self.eventreadtimeout and self.eventreadtimeout:close( )
 +              _ = self.ondisconnect and self:ondisconnect( self.fatalerror ~= "client to close" and self.fatalerror)  -- call ondisconnect listener (wont be the case if handshake failed on connect)
 +              _ = self.conn and self.conn:close( ) -- close connection
 +              _ = self._server and self._server:counter(-1);
 +              self.eventread, self.eventwrite = nil, nil
 +              self.eventstarthandshake, self.eventhandshake, self.eventclose = nil, nil, nil
 +              self.readcallback, self.writecallback = nil, nil
 +      else
 +              self.conn:close( )
 +              self.eventread, self.eventclose = nil, nil
 +              self.interface, self.readcallback = nil, nil
        end
 +      interfacelist[ self ] = nil
 +      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
 +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
 -      function interface_mt:lock_read(switch)
 -              if switch then
 -                      return self:pause();
 -              else
 -                      return self:resume();
 -              end
 +--TODO: Deprecate
 +function interface_mt:lock_read(switch)
 +      if switch then
 +              return self:pause();
 +      else
 +              return self:resume();
        end
 +end
  
 -      function interface_mt:pause()
 -              return self:_lock(self.nointerface, true, self.nowriting);
 -      end
 +function interface_mt:pause()
 +      return self:_lock(self.nointerface, true, self.nowriting);
 +end
  
 -      function interface_mt:resume()
 -              self:_lock(self.nointerface, false, self.nowriting);
 +function interface_mt:resume()
 +      self:_lock(self.nointerface, false, self.nowriting);
-       if not self.eventread then
+               if self.readcallback and not self.eventread then
 -                      self.eventread = addevent( base, self.conn, EV_READ, self.readcallback, cfg.READ_TIMEOUT );  -- register callback
 +              self.eventread = addevent( base, self.conn, EV_READ, self.readcallback, cfg.READ_TIMEOUT );  -- register callback
+                       return true;
 -              end
        end
 +end
  
 -      function interface_mt:counter(c)
 -              if c then
 -                      self._connections = self._connections + c
 -              end
 -              return self._connections
 -      end
 -
 -      -- Public methods
 -      function interface_mt:write(data)
 -              if self.nowriting then return nil, "locked" end
 -              --vdebug( "try to send data to client, id/data:", self.id, data )
 -              data = tostring( data )
 -              local len = #data
 -              local total = len + self.writebufferlen
 -              if total > cfg.MAX_SEND_LENGTH then  -- check buffer length
 -                      local err = "send buffer exceeded"
 -                      debug( "error:", err )  -- to much, check your app
 -                      return nil, err
 -              end
 -              t_insert(self.writebuffer, data) -- new buffer
 -              self.writebufferlen = total
 -              if not self.eventwrite then  -- register new write event
 -                      --vdebug( "register new write event" )
 -                      self.eventwrite = addevent( base, self.conn, EV_WRITE, self.writecallback, cfg.WRITE_TIMEOUT )
 -              end
 -              return true
 +function interface_mt:counter(c)
 +      if c then
 +              self._connections = self._connections + c
        end
 -      function interface_mt:close()
 -              if self.nointerface then return nil, "locked"; end
 -              debug( "try to close client connection with id:", self.id )
 -              if self.type == "client" then
 -                      self.fatalerror = "client to close"
 -                      if self.eventwrite then -- wait for incomplete write request
 -                              self:_lock( true, true, false )
 -                              debug "closing delayed until writebuffer is empty"
 -                              return nil, "writebuffer not empty, waiting"
 -                      else -- close now
 -                              self:_lock( true, true, true )
 -                              self:_close()
 -                              return true
 -                      end
 -              else
 -                      debug( "try to close server with id:", tostring(self.id))
 -                      self.fatalerror = "server to close"
 -                      self:_lock( true )
 -                      self:_close( 0 )
 +      return self._connections
 +end
 +
 +-- Public methods
 +function interface_mt:write(data)
 +      if self.nowriting then return nil, "locked" end
 +      --vdebug( "try to send data to client, id/data:", self.id, data )
 +      data = tostring( data )
 +      local len = #data
 +      local total = len + self.writebufferlen
 +      if total > cfg.MAX_SEND_LENGTH then  -- check buffer length
 +              local err = "send buffer exceeded"
 +              debug( "error:", err )  -- to much, check your app
 +              return nil, err
 +      end
 +      t_insert(self.writebuffer, data) -- new buffer
 +      self.writebufferlen = total
 +      if not self.eventwrite then  -- register new write event
 +              --vdebug( "register new write event" )
 +              self.eventwrite = addevent( base, self.conn, EV_WRITE, self.writecallback, cfg.WRITE_TIMEOUT )
 +      end
 +      return true
 +end
 +function interface_mt:close()
 +      if self.nointerface then return nil, "locked"; end
 +      debug( "try to close client connection with id:", self.id )
 +      if self.type == "client" then
 +              self.fatalerror = "client to close"
 +              if self.eventwrite then -- wait for incomplete write request
 +                      self:_lock( true, true, false )
 +                      debug "closing delayed until writebuffer is empty"
 +                      return nil, "writebuffer not empty, waiting"
 +              else -- close now
 +                      self:_lock( true, true, true )
 +                      self:_close()
                        return true
                end
 +      else
 +              debug( "try to close server with id:", tostring(self.id))
 +              self.fatalerror = "server to close"
 +              self:_lock( true )
 +              self:_close( 0 )
 +              return true
        end
 +end
  
 -      function interface_mt:socket()
 -              return self.conn
 -      end
 +function interface_mt:socket()
 +      return self.conn
 +end
  
 -      function interface_mt:server()
 -              return self._server or self;
 -      end
 +function interface_mt:server()
 +      return self._server or self;
 +end
  
 -      function interface_mt:port()
 -              return self._port
 -      end
 +function interface_mt:port()
 +      return self._port
 +end
  
 -      function interface_mt:serverport()
 -              return self._serverport
 -      end
 +function interface_mt:serverport()
 +      return self._serverport
 +end
  
 -      function interface_mt:ip()
 -              return self._ip
 -      end
 +function interface_mt:ip()
 +      return self._ip
 +end
  
 -      function interface_mt:ssl()
 -              return self._usingssl
 -      end
 -      interface_mt.clientport = interface_mt.port -- COMPAT server_select
 +function interface_mt:ssl()
 +      return self._usingssl
 +end
 +interface_mt.clientport = interface_mt.port -- COMPAT server_select
  
 -      function interface_mt:type()
 -              return self._type or "client"
 -      end
 +function interface_mt:type()
 +      return self._type or "client"
 +end
  
 -      function interface_mt:connections()
 -              return self._connections
 -      end
 +function interface_mt:connections()
 +      return self._connections
 +end
  
 -      function interface_mt:address()
 -              return self.addr
 -      end
 +function interface_mt:address()
 +      return self.addr
 +end
  
 -      function interface_mt:set_sslctx(sslctx)
 -              self._sslctx = sslctx;
 -              if sslctx then
 -                      self.starttls = nil; -- use starttls() of interface_mt
 -              else
 -                      self.starttls = false; -- prevent starttls()
 -              end
 +function interface_mt:set_sslctx(sslctx)
 +      self._sslctx = sslctx;
 +      if sslctx then
 +              self.starttls = nil; -- use starttls() of interface_mt
 +      else
 +              self.starttls = false; -- prevent starttls()
        end
 +end
  
 -      function interface_mt:set_mode(pattern)
 -              if pattern then
 -                      self._pattern = pattern;
 -              end
 -              return self._pattern;
 +function interface_mt:set_mode(pattern)
 +      if pattern then
 +              self._pattern = pattern;
        end
 +      return self._pattern;
 +end
  
  function interface_mt:set_send(new_send) -- luacheck: ignore 212
 -              -- No-op, we always use the underlying connection's send
 -      end
 +      -- 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
 -              self._sslctx = sslctx;
 -              if self._usingssl then  -- startssl was already called
 -                      err = "ssl already active"
 -              end
 -              if err then
 -                      debug( "error:", err )
 -                      return nil, err
 -              end
 -              self._usingssl = true
 -              self.startsslcallback = function( )  -- we have to start the handshake outside of a read/write event
 -                      self.startsslcallback = nil
 -                      self:_start_ssl(call_onconnect);
 -                      self.eventstarthandshake = nil
 -                      return -1
 -              end
 -              if not self.eventwrite then
 -                      self:_lock( true, true, true )  -- lock the interface, to not disturb the handshake
 -                      self.eventstarthandshake = addevent( base, nil, EV_TIMEOUT, self.startsslcallback, 0 )  -- add event to start handshake
 -              else  -- wait until writebuffer is empty
 -                      self:_lock( true, true, false )
 -                      debug "ssl session delayed until writebuffer is empty..."
 -              end
 -              self.starttls = false;
 -              return true
 -      end
 +function interface_mt:starttls(sslctx, call_onconnect)
 +      debug( "try to start ssl at client id:", self.id )
 +      local err
 +      self._sslctx = sslctx;
 +      if self._usingssl then  -- startssl was already called
 +              err = "ssl already active"
 +      end
 +      if err then
 +              debug( "error:", err )
 +              return nil, err
 +      end
 +      self._usingssl = true
 +      self.startsslcallback = function( )  -- we have to start the handshake outside of a read/write event
 +              self.startsslcallback = nil
 +              self:_start_ssl(call_onconnect);
 +              self.eventstarthandshake = nil
 +              return -1
 +      end
 +      if not self.eventwrite then
 +              self:_lock( true, true, true )  -- lock the interface, to not disturb the handshake
 +              self.eventstarthandshake = addevent( base, nil, EV_TIMEOUT, self.startsslcallback, 0 )  -- add event to start handshake
 +      else  -- wait until writebuffer is empty
 +              self:_lock( true, true, false )
 +              debug "ssl session delayed until writebuffer is empty..."
 +      end
 +      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";
 +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:ondetach(); -- Notify listener that it is no longer responsible for this connection
 +function interface_mt:setlistener(listener)
 +      self:ondetach(); -- Notify listener that it is no longer responsible for this connection
        self.onconnect, self.ondisconnect, self.onincoming, self.ontimeout,
        self.onreadtimeout, self.onstatus, self.ondetach
                = listener.onconnect, listener.ondisconnect, listener.onincoming, listener.ontimeout,
@@@ -740,7 -742,7 +741,7 @@@ en
  
  local function newevent( ... )
        return addevent( base, ... )
--      end
++end
  
  local function closeallservers ( arg )
        for item in pairs( interfacelist ) do
@@@ -752,9 -754,9 +753,9 @@@ en
  
  local function setquitting(yes)
        if yes then
--               -- Quit now
--               closeallservers();
--               base:loopexit();
++              -- Quit now
++              closeallservers();
++              base:loopexit();
        end
  end