net/server_event.lua
changeset 7227 07a4c807a94a
parent 7043 bdcea2dd33b8
parent 7226 f911f929ca6c
child 7228 a74f0b7be6bf
child 7339 0d9ac472e58c
equal deleted inserted replaced
7221:6226307f6ac4 7227:07a4c807a94a
    90 local interfacelist = { }
    90 local interfacelist = { }
    91 
    91 
    92 -- Client interface methods
    92 -- Client interface methods
    93 local interface_mt = {}; interface_mt.__index = interface_mt;
    93 local interface_mt = {}; interface_mt.__index = interface_mt;
    94 
    94 
    95 -- Private methods
    95 	-- Private methods
    96 function interface_mt:_close()
    96 	function interface_mt:_close()
    97 	return self:_destroy();
    97 		return self:_destroy();
    98 end
    98 	end
    99 
    99 
   100 function interface_mt:_start_connection(plainssl) -- should be called from addclient
   100 	function interface_mt:_start_connection(plainssl) -- should be called from addclient
   101 	local callback = function( event )
   101 			local callback = function( event )
   102 		if EV_TIMEOUT == event then  -- timeout during connection
   102 				if EV_TIMEOUT == event then  -- timeout during connection
   103 			self.fatalerror = "connection timeout"
   103 					self.fatalerror = "connection timeout"
   104 			self:ontimeout()  -- call timeout listener
   104 					self:ontimeout()  -- call timeout listener
   105 			self:_close()
   105 					self:_close()
   106 			debug( "new connection failed. id:", self.id, "error:", self.fatalerror )
   106 					debug( "new connection failed. id:", self.id, "error:", self.fatalerror )
       
   107 				else
       
   108 			if plainssl and has_luasec then  -- start ssl session
       
   109 						self:starttls(self._sslctx, true)
       
   110 					else  -- normal connection
       
   111 						self:_start_session(true)
       
   112 					end
       
   113 					debug( "new connection established. id:", self.id )
       
   114 				end
       
   115 				self.eventconnect = nil
       
   116 				return -1
       
   117 			end
       
   118 			self.eventconnect = addevent( base, self.conn, EV_WRITE, callback, cfg.CONNECT_TIMEOUT )
       
   119 			return true
       
   120 	end
       
   121 	function interface_mt:_start_session(call_onconnect) -- new session, for example after startssl
       
   122 		if self.type == "client" then
       
   123 			local callback = function( )
       
   124 				self:_lock( false,  false, false )
       
   125 				--vdebug( "start listening on client socket with id:", self.id )
       
   126 				self.eventread = addevent( base, self.conn, EV_READ, self.readcallback, cfg.READ_TIMEOUT );  -- register callback
       
   127 				if call_onconnect then
       
   128 					self:onconnect()
       
   129 				end
       
   130 				self.eventsession = nil
       
   131 				return -1
       
   132 			end
       
   133 			self.eventsession = addevent( base, nil, EV_TIMEOUT, callback, 0 )
   107 		else
   134 		else
   108 			if plainssl and has_luasec then  -- start ssl session
   135 			self:_lock( false )
   109 				self:starttls(self._sslctx, true)
   136 			--vdebug( "start listening on server socket with id:", self.id )
   110 			else  -- normal connection
   137 			self.eventread = addevent( base, self.conn, EV_READ, self.readcallback )  -- register callback
   111 				self:_start_session(true)
   138 		end
   112 			end
   139 		return true
   113 			debug( "new connection established. id:", self.id )
   140 	end
   114 		end
   141 	function interface_mt:_start_ssl(call_onconnect) -- old socket will be destroyed, therefore we have to close read/write events first
   115 		self.eventconnect = nil
   142 			--vdebug( "starting ssl session with client id:", self.id )
   116 		return -1
   143 			local _
   117 	end
   144 			_ = self.eventread and self.eventread:close( )  -- close events; this must be called outside of the event callbacks!
   118 	self.eventconnect = addevent( base, self.conn, EV_WRITE, callback, cfg.CONNECT_TIMEOUT )
   145 			_ = self.eventwrite and self.eventwrite:close( )
   119 	return true
   146 			self.eventread, self.eventwrite = nil, nil
   120 end
   147 			local err
   121 function interface_mt:_start_session(call_onconnect) -- new session, for example after startssl
   148 			self.conn, err = ssl.wrap( self.conn, self._sslctx )
   122 	if self.type == "client" then
   149 			if err then
   123 		local callback = function( )
   150 				self.fatalerror = err
   124 			self:_lock( false,  false, false )
   151 				self.conn = nil  -- cannot be used anymore
   125 			--vdebug( "start listening on client socket with id:", self.id )
       
   126 			self.eventread = addevent( base, self.conn, EV_READ, self.readcallback, cfg.READ_TIMEOUT );  -- register callback
       
   127 			if call_onconnect then
       
   128 				self:onconnect()
       
   129 			end
       
   130 			self.eventsession = nil
       
   131 			return -1
       
   132 		end
       
   133 		self.eventsession = addevent( base, nil, EV_TIMEOUT, callback, 0 )
       
   134 	else
       
   135 		self:_lock( false )
       
   136 		--vdebug( "start listening on server socket with id:", self.id )
       
   137 		self.eventread = addevent( base, self.conn, EV_READ, self.readcallback )  -- register callback
       
   138 	end
       
   139 	return true
       
   140 end
       
   141 function interface_mt:_start_ssl(call_onconnect) -- old socket will be destroyed, therefore we have to close read/write events first
       
   142 	--vdebug( "starting ssl session with client id:", self.id )
       
   143 	local _
       
   144 	_ = self.eventread and self.eventread:close( )  -- close events; this must be called outside of the event callbacks!
       
   145 	_ = self.eventwrite and self.eventwrite:close( )
       
   146 	self.eventread, self.eventwrite = nil, nil
       
   147 	local err
       
   148 	self.conn, err = ssl.wrap( self.conn, self._sslctx )
       
   149 	if err then
       
   150 		self.fatalerror = err
       
   151 		self.conn = nil  -- cannot be used anymore
       
   152 		if call_onconnect then
       
   153 			self.ondisconnect = nil  -- dont call this when client isnt really connected
       
   154 		end
       
   155 		self:_close()
       
   156 		debug( "fatal error while ssl wrapping:", err )
       
   157 		return false
       
   158 	end
       
   159 	self.conn:settimeout( 0 )  -- set non blocking
       
   160 	local handshakecallback = coroutine_wrap(function( event )
       
   161 		local _, err
       
   162 		local attempt = 0
       
   163 		local maxattempt = cfg.MAX_HANDSHAKE_ATTEMPTS
       
   164 		while attempt < maxattempt do  -- no endless loop
       
   165 			attempt = attempt + 1
       
   166 			debug( "ssl handshake of client with id:"..tostring(self)..", attempt:"..attempt )
       
   167 			if attempt > maxattempt then
       
   168 				self.fatalerror = "max handshake attempts exceeded"
       
   169 			elseif EV_TIMEOUT == event then
       
   170 				self.fatalerror = "timeout during handshake"
       
   171 			else
       
   172 				_, err = self.conn:dohandshake( )
       
   173 				if not err then
       
   174 					self:_lock( false, false, false )  -- unlock the interface; sending, closing etc allowed
       
   175 					self.send = self.conn.send  -- caching table lookups with new client object
       
   176 					self.receive = self.conn.receive
       
   177 					if not call_onconnect then  -- trigger listener
       
   178 						self:onstatus("ssl-handshake-complete");
       
   179 					end
       
   180 					self:_start_session( call_onconnect )
       
   181 					debug( "ssl handshake done" )
       
   182 					self.eventhandshake = nil
       
   183 					return -1
       
   184 				end
       
   185 				if err == "wantwrite" then
       
   186 					event = EV_WRITE
       
   187 				elseif err == "wantread" then
       
   188 					event = EV_READ
       
   189 				else
       
   190 					debug( "ssl handshake error:", err )
       
   191 					self.fatalerror = err
       
   192 				end
       
   193 			end
       
   194 			if self.fatalerror then
       
   195 				if call_onconnect then
   152 				if call_onconnect then
   196 					self.ondisconnect = nil  -- dont call this when client isnt really connected
   153 					self.ondisconnect = nil  -- dont call this when client isnt really connected
   197 				end
   154 				end
   198 				self:_close()
   155 				self:_close()
   199 				debug( "handshake failed because:", self.fatalerror )
   156 				debug( "fatal error while ssl wrapping:", err )
   200 				self.eventhandshake = nil
   157 				return false
   201 				return -1
   158 			end
   202 			end
   159 			self.conn:settimeout( 0 )  -- set non blocking
   203 			event = coroutine_yield( event, cfg.HANDSHAKE_TIMEOUT )  -- yield this monster...
   160 	local handshakecallback = coroutine_wrap(function( event )
   204 		end
   161 					local _, err
   205 	end
   162 					local attempt = 0
   206 	)
   163 					local maxattempt = cfg.MAX_HANDSHAKE_ATTEMPTS
   207 	debug "starting handshake..."
   164 					while attempt < maxattempt do  -- no endless loop
   208 	self:_lock( false, true, true )  -- unlock read/write events, but keep interface locked
   165 						attempt = attempt + 1
   209 	self.eventhandshake = addevent( base, self.conn, EV_READWRITE, handshakecallback, cfg.HANDSHAKE_TIMEOUT )
   166 						debug( "ssl handshake of client with id:"..tostring(self)..", attempt:"..attempt )
   210 	return true
   167 						if attempt > maxattempt then
   211 end
   168 							self.fatalerror = "max handshake attempts exceeded"
   212 function interface_mt:_destroy()  -- close this interface + events and call last listener
   169 						elseif EV_TIMEOUT == event then
   213 	debug( "closing client with id:", self.id, self.fatalerror )
   170 							self.fatalerror = "timeout during handshake"
   214 	self:_lock( true, true, true )  -- first of all, lock the interface to avoid further actions
   171 						else
   215 	local _
   172 							_, err = self.conn:dohandshake( )
   216 	_ = self.eventread and self.eventread:close( )
   173 							if not err then
   217 	if self.type == "client" then
   174 								self:_lock( false, false, false )  -- unlock the interface; sending, closing etc allowed
   218 		_ = self.eventwrite and self.eventwrite:close( )
   175 								self.send = self.conn.send  -- caching table lookups with new client object
   219 		_ = self.eventhandshake and self.eventhandshake:close( )
   176 								self.receive = self.conn.receive
   220 		_ = self.eventstarthandshake and self.eventstarthandshake:close( )
   177 								if not call_onconnect then  -- trigger listener
   221 		_ = self.eventconnect and self.eventconnect:close( )
   178 									self:onstatus("ssl-handshake-complete");
   222 		_ = self.eventsession and self.eventsession:close( )
   179 								end
   223 		_ = self.eventwritetimeout and self.eventwritetimeout:close( )
   180 								self:_start_session( call_onconnect )
   224 		_ = self.eventreadtimeout and self.eventreadtimeout:close( )
   181 								debug( "ssl handshake done" )
   225 		_ = 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)
   182 								self.eventhandshake = nil
   226 		_ = self.conn and self.conn:close( ) -- close connection
   183 								return -1
   227 		_ = self._server and self._server:counter(-1);
   184 							end
   228 		self.eventread, self.eventwrite = nil, nil
   185 							if err == "wantwrite" then
   229 		self.eventstarthandshake, self.eventhandshake, self.eventclose = nil, nil, nil
   186 								event = EV_WRITE
   230 		self.readcallback, self.writecallback = nil, nil
   187 							elseif err == "wantread" then
   231 	else
   188 								event = EV_READ
   232 		self.conn:close( )
   189 							else
   233 		self.eventread, self.eventclose = nil, nil
   190 								debug( "ssl handshake error:", err )
   234 		self.interface, self.readcallback = nil, nil
   191 								self.fatalerror = err
   235 	end
   192 							end
       
   193 						end
       
   194 						if self.fatalerror then
       
   195 							if call_onconnect then
       
   196 								self.ondisconnect = nil  -- dont call this when client isnt really connected
       
   197 							end
       
   198 							self:_close()
       
   199 							debug( "handshake failed because:", self.fatalerror )
       
   200 							self.eventhandshake = nil
       
   201 							return -1
       
   202 						end
       
   203 						event = coroutine_yield( event, cfg.HANDSHAKE_TIMEOUT )  -- yield this monster...
       
   204 					end
       
   205 				end
       
   206 			)
       
   207 			debug "starting handshake..."
       
   208 			self:_lock( false, true, true )  -- unlock read/write events, but keep interface locked
       
   209 			self.eventhandshake = addevent( base, self.conn, EV_READWRITE, handshakecallback, cfg.HANDSHAKE_TIMEOUT )
       
   210 			return true
       
   211 	end
       
   212 	function interface_mt:_destroy()  -- close this interface + events and call last listener
       
   213 			debug( "closing client with id:", self.id, self.fatalerror )
       
   214 			self:_lock( true, true, true )  -- first of all, lock the interface to avoid further actions
       
   215 			local _
       
   216 			_ = self.eventread and self.eventread:close( )
       
   217 			if self.type == "client" then
       
   218 				_ = self.eventwrite and self.eventwrite:close( )
       
   219 				_ = self.eventhandshake and self.eventhandshake:close( )
       
   220 				_ = self.eventstarthandshake and self.eventstarthandshake:close( )
       
   221 				_ = self.eventconnect and self.eventconnect:close( )
       
   222 				_ = self.eventsession and self.eventsession:close( )
       
   223 				_ = self.eventwritetimeout and self.eventwritetimeout:close( )
       
   224 				_ = self.eventreadtimeout and self.eventreadtimeout:close( )
       
   225 				_ = 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)
       
   226 				_ = self.conn and self.conn:close( ) -- close connection
       
   227 				_ = self._server and self._server:counter(-1);
       
   228 				self.eventread, self.eventwrite = nil, nil
       
   229 				self.eventstarthandshake, self.eventhandshake, self.eventclose = nil, nil, nil
       
   230 				self.readcallback, self.writecallback = nil, nil
       
   231 			else
       
   232 				self.conn:close( )
       
   233 				self.eventread, self.eventclose = nil, nil
       
   234 				self.interface, self.readcallback = nil, nil
       
   235 			end
   236 	interfacelist[ self ] = nil
   236 	interfacelist[ self ] = nil
   237 	return true
   237 			return true
   238 end
   238 	end
   239 
   239 
   240 function interface_mt:_lock(nointerface, noreading, nowriting)  -- lock or unlock this interface or events
   240 	function interface_mt:_lock(nointerface, noreading, nowriting)  -- lock or unlock this interface or events
   241 	self.nointerface, self.noreading, self.nowriting = nointerface, noreading, nowriting
   241 			self.nointerface, self.noreading, self.nowriting = nointerface, noreading, nowriting
   242 	return nointerface, noreading, nowriting
   242 			return nointerface, noreading, nowriting
   243 end
   243 	end
   244 
   244 
   245 --TODO: Deprecate
   245 	--TODO: Deprecate
   246 function interface_mt:lock_read(switch)
   246 	function interface_mt:lock_read(switch)
   247 	if switch then
   247 		if switch then
   248 		return self:pause();
   248 			return self:pause();
   249 	else
   249 		else
   250 		return self:resume();
   250 			return self:resume();
   251 	end
   251 		end
   252 end
   252 	end
   253 
   253 
   254 function interface_mt:pause()
   254 	function interface_mt:pause()
   255 	return self:_lock(self.nointerface, true, self.nowriting);
   255 		return self:_lock(self.nointerface, true, self.nowriting);
   256 end
   256 	end
   257 
   257 
   258 function interface_mt:resume()
   258 	function interface_mt:resume()
   259 	self:_lock(self.nointerface, false, self.nowriting);
   259 		self:_lock(self.nointerface, false, self.nowriting);
   260 	if not self.eventread then
   260 		if self.readcallback and not self.eventread then
   261 		self.eventread = addevent( base, self.conn, EV_READ, self.readcallback, cfg.READ_TIMEOUT );  -- register callback
   261 			self.eventread = addevent( base, self.conn, EV_READ, self.readcallback, cfg.READ_TIMEOUT );  -- register callback
   262 	end
   262 			return true;
   263 end
   263 		end
   264 
   264 	end
   265 function interface_mt:counter(c)
   265 
   266 	if c then
   266 	function interface_mt:counter(c)
   267 		self._connections = self._connections + c
   267 		if c then
   268 	end
   268 			self._connections = self._connections + c
   269 	return self._connections
   269 		end
   270 end
   270 		return self._connections
   271 
   271 	end
   272 -- Public methods
   272 
   273 function interface_mt:write(data)
   273 	-- Public methods
   274 	if self.nowriting then return nil, "locked" end
   274 	function interface_mt:write(data)
   275 	--vdebug( "try to send data to client, id/data:", self.id, data )
   275 		if self.nowriting then return nil, "locked" end
   276 	data = tostring( data )
   276 		--vdebug( "try to send data to client, id/data:", self.id, data )
   277 	local len = #data
   277 		data = tostring( data )
   278 	local total = len + self.writebufferlen
   278 		local len = #data
   279 	if total > cfg.MAX_SEND_LENGTH then  -- check buffer length
   279 		local total = len + self.writebufferlen
   280 		local err = "send buffer exceeded"
   280 		if total > cfg.MAX_SEND_LENGTH then  -- check buffer length
   281 		debug( "error:", err )  -- to much, check your app
   281 			local err = "send buffer exceeded"
   282 		return nil, err
   282 			debug( "error:", err )  -- to much, check your app
   283 	end
   283 			return nil, err
   284 	t_insert(self.writebuffer, data) -- new buffer
   284 		end
   285 	self.writebufferlen = total
   285 		t_insert(self.writebuffer, data) -- new buffer
   286 	if not self.eventwrite then  -- register new write event
   286 		self.writebufferlen = total
   287 		--vdebug( "register new write event" )
   287 		if not self.eventwrite then  -- register new write event
   288 		self.eventwrite = addevent( base, self.conn, EV_WRITE, self.writecallback, cfg.WRITE_TIMEOUT )
   288 			--vdebug( "register new write event" )
   289 	end
   289 			self.eventwrite = addevent( base, self.conn, EV_WRITE, self.writecallback, cfg.WRITE_TIMEOUT )
   290 	return true
   290 		end
   291 end
   291 		return true
   292 function interface_mt:close()
   292 	end
   293 	if self.nointerface then return nil, "locked"; end
   293 	function interface_mt:close()
   294 	debug( "try to close client connection with id:", self.id )
   294 		if self.nointerface then return nil, "locked"; end
   295 	if self.type == "client" then
   295 		debug( "try to close client connection with id:", self.id )
   296 		self.fatalerror = "client to close"
   296 		if self.type == "client" then
   297 		if self.eventwrite then -- wait for incomplete write request
   297 			self.fatalerror = "client to close"
       
   298 			if self.eventwrite then -- wait for incomplete write request
       
   299 				self:_lock( true, true, false )
       
   300 				debug "closing delayed until writebuffer is empty"
       
   301 				return nil, "writebuffer not empty, waiting"
       
   302 			else -- close now
       
   303 				self:_lock( true, true, true )
       
   304 				self:_close()
       
   305 				return true
       
   306 			end
       
   307 		else
       
   308 			debug( "try to close server with id:", tostring(self.id))
       
   309 			self.fatalerror = "server to close"
       
   310 			self:_lock( true )
       
   311 			self:_close( 0 )
       
   312 			return true
       
   313 		end
       
   314 	end
       
   315 
       
   316 	function interface_mt:socket()
       
   317 		return self.conn
       
   318 	end
       
   319 
       
   320 	function interface_mt:server()
       
   321 		return self._server or self;
       
   322 	end
       
   323 
       
   324 	function interface_mt:port()
       
   325 		return self._port
       
   326 	end
       
   327 
       
   328 	function interface_mt:serverport()
       
   329 		return self._serverport
       
   330 	end
       
   331 
       
   332 	function interface_mt:ip()
       
   333 		return self._ip
       
   334 	end
       
   335 
       
   336 	function interface_mt:ssl()
       
   337 		return self._usingssl
       
   338 	end
       
   339 	interface_mt.clientport = interface_mt.port -- COMPAT server_select
       
   340 
       
   341 	function interface_mt:type()
       
   342 		return self._type or "client"
       
   343 	end
       
   344 
       
   345 	function interface_mt:connections()
       
   346 		return self._connections
       
   347 	end
       
   348 
       
   349 	function interface_mt:address()
       
   350 		return self.addr
       
   351 	end
       
   352 
       
   353 	function interface_mt:set_sslctx(sslctx)
       
   354 		self._sslctx = sslctx;
       
   355 		if sslctx then
       
   356 			self.starttls = nil; -- use starttls() of interface_mt
       
   357 		else
       
   358 			self.starttls = false; -- prevent starttls()
       
   359 		end
       
   360 	end
       
   361 
       
   362 	function interface_mt:set_mode(pattern)
       
   363 		if pattern then
       
   364 			self._pattern = pattern;
       
   365 		end
       
   366 		return self._pattern;
       
   367 	end
       
   368 
       
   369 function interface_mt:set_send(new_send) -- luacheck: ignore 212
       
   370 		-- No-op, we always use the underlying connection's send
       
   371 	end
       
   372 
       
   373 	function interface_mt:starttls(sslctx, call_onconnect)
       
   374 		debug( "try to start ssl at client id:", self.id )
       
   375 		local err
       
   376 		self._sslctx = sslctx;
       
   377 		if self._usingssl then  -- startssl was already called
       
   378 			err = "ssl already active"
       
   379 		end
       
   380 		if err then
       
   381 			debug( "error:", err )
       
   382 			return nil, err
       
   383 		end
       
   384 		self._usingssl = true
       
   385 		self.startsslcallback = function( )  -- we have to start the handshake outside of a read/write event
       
   386 			self.startsslcallback = nil
       
   387 			self:_start_ssl(call_onconnect);
       
   388 			self.eventstarthandshake = nil
       
   389 			return -1
       
   390 		end
       
   391 		if not self.eventwrite then
       
   392 			self:_lock( true, true, true )  -- lock the interface, to not disturb the handshake
       
   393 			self.eventstarthandshake = addevent( base, nil, EV_TIMEOUT, self.startsslcallback, 0 )  -- add event to start handshake
       
   394 		else  -- wait until writebuffer is empty
   298 			self:_lock( true, true, false )
   395 			self:_lock( true, true, false )
   299 			debug "closing delayed until writebuffer is empty"
   396 			debug "ssl session delayed until writebuffer is empty..."
   300 			return nil, "writebuffer not empty, waiting"
   397 		end
   301 		else -- close now
   398 		self.starttls = false;
   302 			self:_lock( true, true, true )
       
   303 			self:_close()
       
   304 			return true
       
   305 		end
       
   306 	else
       
   307 		debug( "try to close server with id:", tostring(self.id))
       
   308 		self.fatalerror = "server to close"
       
   309 		self:_lock( true )
       
   310 		self:_close( 0 )
       
   311 		return true
   399 		return true
   312 	end
   400 	end
   313 end
   401 
   314 
   402 	function interface_mt:setoption(option, value)
   315 function interface_mt:socket()
   403 		if self.conn.setoption then
   316 	return self.conn
   404 			return self.conn:setoption(option, value);
   317 end
   405 		end
   318 
   406 		return false, "setoption not implemented";
   319 function interface_mt:server()
   407 	end
   320 	return self._server or self;
   408 
   321 end
   409 	function interface_mt:setlistener(listener)
   322 
   410 		self:ondetach(); -- Notify listener that it is no longer responsible for this connection
   323 function interface_mt:port()
       
   324 	return self._port
       
   325 end
       
   326 
       
   327 function interface_mt:serverport()
       
   328 	return self._serverport
       
   329 end
       
   330 
       
   331 function interface_mt:ip()
       
   332 	return self._ip
       
   333 end
       
   334 
       
   335 function interface_mt:ssl()
       
   336 	return self._usingssl
       
   337 end
       
   338 interface_mt.clientport = interface_mt.port -- COMPAT server_select
       
   339 
       
   340 function interface_mt:type()
       
   341 	return self._type or "client"
       
   342 end
       
   343 
       
   344 function interface_mt:connections()
       
   345 	return self._connections
       
   346 end
       
   347 
       
   348 function interface_mt:address()
       
   349 	return self.addr
       
   350 end
       
   351 
       
   352 function interface_mt:set_sslctx(sslctx)
       
   353 	self._sslctx = sslctx;
       
   354 	if sslctx then
       
   355 		self.starttls = nil; -- use starttls() of interface_mt
       
   356 	else
       
   357 		self.starttls = false; -- prevent starttls()
       
   358 	end
       
   359 end
       
   360 
       
   361 function interface_mt:set_mode(pattern)
       
   362 	if pattern then
       
   363 		self._pattern = pattern;
       
   364 	end
       
   365 	return self._pattern;
       
   366 end
       
   367 
       
   368 function interface_mt:set_send(new_send) -- luacheck: ignore 212
       
   369 	-- No-op, we always use the underlying connection's send
       
   370 end
       
   371 
       
   372 function interface_mt:starttls(sslctx, call_onconnect)
       
   373 	debug( "try to start ssl at client id:", self.id )
       
   374 	local err
       
   375 	self._sslctx = sslctx;
       
   376 	if self._usingssl then  -- startssl was already called
       
   377 		err = "ssl already active"
       
   378 	end
       
   379 	if err then
       
   380 		debug( "error:", err )
       
   381 		return nil, err
       
   382 	end
       
   383 	self._usingssl = true
       
   384 	self.startsslcallback = function( )  -- we have to start the handshake outside of a read/write event
       
   385 		self.startsslcallback = nil
       
   386 		self:_start_ssl(call_onconnect);
       
   387 		self.eventstarthandshake = nil
       
   388 		return -1
       
   389 	end
       
   390 	if not self.eventwrite then
       
   391 		self:_lock( true, true, true )  -- lock the interface, to not disturb the handshake
       
   392 		self.eventstarthandshake = addevent( base, nil, EV_TIMEOUT, self.startsslcallback, 0 )  -- add event to start handshake
       
   393 	else  -- wait until writebuffer is empty
       
   394 		self:_lock( true, true, false )
       
   395 		debug "ssl session delayed until writebuffer is empty..."
       
   396 	end
       
   397 	self.starttls = false;
       
   398 	return true
       
   399 end
       
   400 
       
   401 function interface_mt:setoption(option, value)
       
   402 	if self.conn.setoption then
       
   403 		return self.conn:setoption(option, value);
       
   404 	end
       
   405 	return false, "setoption not implemented";
       
   406 end
       
   407 
       
   408 function interface_mt:setlistener(listener)
       
   409 	self:ondetach(); -- Notify listener that it is no longer responsible for this connection
       
   410 	self.onconnect, self.ondisconnect, self.onincoming, self.ontimeout,
   411 	self.onconnect, self.ondisconnect, self.onincoming, self.ontimeout,
   411 	self.onreadtimeout, self.onstatus, self.ondetach
   412 	self.onreadtimeout, self.onstatus, self.ondetach
   412 		= listener.onconnect, listener.ondisconnect, listener.onincoming, listener.ontimeout,
   413 		= listener.onconnect, listener.ondisconnect, listener.onincoming, listener.ontimeout,
   413 		  listener.onreadtimeout, listener.onstatus, listener.ondetach;
   414 		  listener.onreadtimeout, listener.onstatus, listener.ondetach;
   414 end
   415 	end
   415 
   416 
   416 -- Stub handlers
   417 	-- Stub handlers
   417 function interface_mt:onconnect()
   418 	function interface_mt:onconnect()
   418 end
   419 	end
   419 function interface_mt:onincoming()
   420 	function interface_mt:onincoming()
   420 end
   421 	end
   421 function interface_mt:ondisconnect()
   422 	function interface_mt:ondisconnect()
   422 end
   423 	end
   423 function interface_mt:ontimeout()
   424 	function interface_mt:ontimeout()
   424 end
   425 	end
   425 function interface_mt:onreadtimeout()
   426 function interface_mt:onreadtimeout()
   426 	self.fatalerror = "timeout during receiving"
   427 	self.fatalerror = "timeout during receiving"
   427 	debug( "connection failed:", self.fatalerror )
   428 	debug( "connection failed:", self.fatalerror )
   428 	self:_close()
   429 	self:_close()
   429 	self.eventread = nil
   430 	self.eventread = nil
   430 end
   431 end
   431 function interface_mt:ondrain()
   432 	function interface_mt:ondrain()
   432 end
   433 	end
   433 function interface_mt:ondetach()
   434 	function interface_mt:ondetach()
   434 end
   435 	end
   435 function interface_mt:onstatus()
   436 	function interface_mt:onstatus()
   436 end
   437 	end
   437 
   438 
   438 -- End of client interface methods
   439 -- End of client interface methods
   439 
   440 
   440 local function handleclient( client, ip, port, server, pattern, listener, sslctx )  -- creates an client interface
   441 local function handleclient( client, ip, port, server, pattern, listener, sslctx )  -- creates an client interface
   441 	--vdebug("creating client interfacce...")
   442 		--vdebug("creating client interfacce...")
   442 	local interface = {
   443 		local interface = {
   443 		type = "client";
   444 			type = "client";
   444 		conn = client;
   445 			conn = client;
   445 		currenttime = socket_gettime( );  -- safe the origin
   446 			currenttime = socket_gettime( );  -- safe the origin
   446 		writebuffer = {};  -- writebuffer
   447 			writebuffer = {};  -- writebuffer
   447 		writebufferlen = 0;  -- length of writebuffer
   448 			writebufferlen = 0;  -- length of writebuffer
   448 		send = client.send;  -- caching table lookups
   449 			send = client.send;  -- caching table lookups
   449 		receive = client.receive;
   450 			receive = client.receive;
   450 		onconnect = listener.onconnect;  -- will be called when client disconnects
   451 			onconnect = listener.onconnect;  -- will be called when client disconnects
   451 		ondisconnect = listener.ondisconnect;  -- will be called when client disconnects
   452 			ondisconnect = listener.ondisconnect;  -- will be called when client disconnects
   452 		onincoming = listener.onincoming;  -- will be called when client sends data
   453 			onincoming = listener.onincoming;  -- will be called when client sends data
   453 		ontimeout = listener.ontimeout; -- called when fatal socket timeout occurs
   454 			ontimeout = listener.ontimeout; -- called when fatal socket timeout occurs
   454 		onreadtimeout = listener.onreadtimeout; -- called when socket inactivity timeout occurs
   455 		onreadtimeout = listener.onreadtimeout; -- called when socket inactivity timeout occurs
   455 		ondrain = listener.ondrain; -- called when writebuffer is empty
   456 			ondrain = listener.ondrain; -- called when writebuffer is empty
   456 		ondetach = listener.ondetach; -- called when disassociating this listener from this connection
   457 			ondetach = listener.ondetach; -- called when disassociating this listener from this connection
   457 		onstatus = listener.onstatus; -- called for status changes (e.g. of SSL/TLS)
   458 			onstatus = listener.onstatus; -- called for status changes (e.g. of SSL/TLS)
   458 		eventread = false, eventwrite = false, eventclose = false,
   459 			eventread = false, eventwrite = false, eventclose = false,
   459 		eventhandshake = false, eventstarthandshake = false;  -- event handler
   460 			eventhandshake = false, eventstarthandshake = false;  -- event handler
   460 		eventconnect = false, eventsession = false;  -- more event handler...
   461 			eventconnect = false, eventsession = false;  -- more event handler...
   461 		eventwritetimeout = false;  -- even more event handler...
   462 			eventwritetimeout = false;  -- even more event handler...
   462 		eventreadtimeout = false;
   463 			eventreadtimeout = false;
   463 		fatalerror = false;  -- error message
   464 			fatalerror = false;  -- error message
   464 		writecallback = false;  -- will be called on write events
   465 			writecallback = false;  -- will be called on write events
   465 		readcallback = false;  -- will be called on read events
   466 			readcallback = false;  -- will be called on read events
   466 		nointerface = true;  -- lock/unlock parameter of this interface
   467 			nointerface = true;  -- lock/unlock parameter of this interface
   467 		noreading = false, nowriting = false;  -- locks of the read/writecallback
   468 			noreading = false, nowriting = false;  -- locks of the read/writecallback
   468 		startsslcallback = false;  -- starting handshake callback
   469 			startsslcallback = false;  -- starting handshake callback
   469 		position = false;  -- position of client in interfacelist
   470 			position = false;  -- position of client in interfacelist
   470 
   471 
   471 		-- Properties
   472 			-- Properties
   472 		_ip = ip, _port = port, _server = server, _pattern = pattern,
   473 			_ip = ip, _port = port, _server = server, _pattern = pattern,
   473 		_serverport = (server and server:port() or nil),
   474 			_serverport = (server and server:port() or nil),
   474 		_sslctx = sslctx; -- parameters
   475 			_sslctx = sslctx; -- parameters
   475 		_usingssl = false;  -- client is using ssl;
   476 			_usingssl = false;  -- client is using ssl;
   476 	}
   477 		}
   477 	if not has_luasec then interface.starttls = false; end
   478 	if not has_luasec then interface.starttls = false; end
   478 	interface.id = tostring(interface):match("%x+$");
   479 		interface.id = tostring(interface):match("%x+$");
   479 	interface.writecallback = function( event )  -- called on write events
   480 		interface.writecallback = function( event )  -- called on write events
   480 		--vdebug( "new client write event, id/ip/port:", interface, ip, port )
   481 			--vdebug( "new client write event, id/ip/port:", interface, ip, port )
   481 		if interface.nowriting or ( interface.fatalerror and ( "client to close" ~= interface.fatalerror ) ) then  -- leave this event
   482 			if interface.nowriting or ( interface.fatalerror and ( "client to close" ~= interface.fatalerror ) ) then  -- leave this event
   482 			--vdebug( "leaving this event because:", interface.nowriting or interface.fatalerror )
   483 				--vdebug( "leaving this event because:", interface.nowriting or interface.fatalerror )
   483 			interface.eventwrite = false
   484 				interface.eventwrite = false
   484 			return -1
       
   485 		end
       
   486 		if EV_TIMEOUT == event then  -- took too long to write some data to socket -> disconnect
       
   487 			interface.fatalerror = "timeout during writing"
       
   488 			debug( "writing failed:", interface.fatalerror )
       
   489 			interface:_close()
       
   490 			interface.eventwrite = false
       
   491 			return -1
       
   492 		else  -- can write :)
       
   493 			if interface._usingssl then  -- handle luasec
       
   494 				if interface.eventreadtimeout then  -- we have to read first
       
   495 					local ret = interface.readcallback( )  -- call readcallback
       
   496 					--vdebug( "tried to read in writecallback, result:", ret )
       
   497 				end
       
   498 				if interface.eventwritetimeout then  -- luasec only
       
   499 					interface.eventwritetimeout:close( )  -- first we have to close timeout event which where regged after a wantread error
       
   500 					interface.eventwritetimeout = false
       
   501 				end
       
   502 			end
       
   503 			interface.writebuffer = { t_concat(interface.writebuffer) }
       
   504 			local succ, err, byte = interface.conn:send( interface.writebuffer[1], 1, interface.writebufferlen )
       
   505 			--vdebug( "write data:", interface.writebuffer, "error:", err, "part:", byte )
       
   506 			if succ then  -- writing succesful
       
   507 				interface.writebuffer[1] = nil
       
   508 				interface.writebufferlen = 0
       
   509 				interface:ondrain();
       
   510 				if interface.fatalerror then
       
   511 					debug "closing client after writing"
       
   512 					interface:_close()  -- close interface if needed
       
   513 				elseif interface.startsslcallback then  -- start ssl connection if needed
       
   514 					debug "starting ssl handshake after writing"
       
   515 					interface.eventstarthandshake = addevent( base, nil, EV_TIMEOUT, interface.startsslcallback, 0 )
       
   516 				elseif interface.eventreadtimeout then
       
   517 					return EV_WRITE, EV_TIMEOUT
       
   518 				end
       
   519 				interface.eventwrite = nil
       
   520 				return -1
   485 				return -1
   521 			elseif byte and (err == "timeout" or err == "wantwrite") then  -- want write again
   486 			end
   522 				--vdebug( "writebuffer is not empty:", err )
   487 			if EV_TIMEOUT == event then  -- took too long to write some data to socket -> disconnect
       
   488 				interface.fatalerror = "timeout during writing"
       
   489 				debug( "writing failed:", interface.fatalerror )
       
   490 				interface:_close()
       
   491 				interface.eventwrite = false
       
   492 				return -1
       
   493 			else  -- can write :)
       
   494 				if interface._usingssl then  -- handle luasec
       
   495 					if interface.eventreadtimeout then  -- we have to read first
       
   496 						local ret = interface.readcallback( )  -- call readcallback
       
   497 						--vdebug( "tried to read in writecallback, result:", ret )
       
   498 					end
       
   499 					if interface.eventwritetimeout then  -- luasec only
       
   500 						interface.eventwritetimeout:close( )  -- first we have to close timeout event which where regged after a wantread error
       
   501 						interface.eventwritetimeout = false
       
   502 					end
       
   503 				end
       
   504 				interface.writebuffer = { t_concat(interface.writebuffer) }
       
   505 				local succ, err, byte = interface.conn:send( interface.writebuffer[1], 1, interface.writebufferlen )
       
   506 				--vdebug( "write data:", interface.writebuffer, "error:", err, "part:", byte )
       
   507 				if succ then  -- writing succesful
       
   508 					interface.writebuffer[1] = nil
       
   509 					interface.writebufferlen = 0
       
   510 					interface:ondrain();
       
   511 					if interface.fatalerror then
       
   512 						debug "closing client after writing"
       
   513 						interface:_close()  -- close interface if needed
       
   514 					elseif interface.startsslcallback then  -- start ssl connection if needed
       
   515 						debug "starting ssl handshake after writing"
       
   516 						interface.eventstarthandshake = addevent( base, nil, EV_TIMEOUT, interface.startsslcallback, 0 )
       
   517 					elseif interface.eventreadtimeout then
       
   518 						return EV_WRITE, EV_TIMEOUT
       
   519 					end
       
   520 					interface.eventwrite = nil
       
   521 					return -1
       
   522 				elseif byte and (err == "timeout" or err == "wantwrite") then  -- want write again
       
   523 					--vdebug( "writebuffer is not empty:", err )
   523 				interface.writebuffer[1] = s_sub( interface.writebuffer[1], byte + 1, interface.writebufferlen )  -- new buffer
   524 				interface.writebuffer[1] = s_sub( interface.writebuffer[1], byte + 1, interface.writebufferlen )  -- new buffer
   524 				interface.writebufferlen = interface.writebufferlen - byte
   525 					interface.writebufferlen = interface.writebufferlen - byte
   525 				if "wantread" == err then  -- happens only with luasec
   526 					if "wantread" == err then  -- happens only with luasec
   526 					local callback = function( )
   527 						local callback = function( )
   527 						interface:_close()
   528 							interface:_close()
   528 						interface.eventwritetimeout = nil
   529 							interface.eventwritetimeout = nil
   529 						return -1;
   530 							return -1;
       
   531 						end
       
   532 						interface.eventwritetimeout = addevent( base, nil, EV_TIMEOUT, callback, cfg.WRITE_TIMEOUT )  -- reg a new timeout event
       
   533 						debug( "wantread during write attempt, reg it in readcallback but dont know what really happens next..." )
       
   534 						-- hopefully this works with luasec; its simply not possible to use 2 different write events on a socket in luaevent
       
   535 						return -1
   530 					end
   536 					end
   531 					interface.eventwritetimeout = addevent( base, nil, EV_TIMEOUT, callback, cfg.WRITE_TIMEOUT )  -- reg a new timeout event
   537 					return EV_WRITE, cfg.WRITE_TIMEOUT
   532 					debug( "wantread during write attempt, reg it in readcallback but dont know what really happens next..." )
   538 				else  -- connection was closed during writing or fatal error
   533 					-- hopefully this works with luasec; its simply not possible to use 2 different write events on a socket in luaevent
   539 					interface.fatalerror = err or "fatal error"
       
   540 					debug( "connection failed in write event:", interface.fatalerror )
       
   541 					interface:_close()
       
   542 					interface.eventwrite = nil
   534 					return -1
   543 					return -1
   535 				end
   544 				end
   536 				return EV_WRITE, cfg.WRITE_TIMEOUT
   545 			end
   537 			else  -- connection was closed during writing or fatal error
   546 		end
   538 				interface.fatalerror = err or "fatal error"
   547 
   539 				debug( "connection failed in write event:", interface.fatalerror )
   548 		interface.readcallback = function( event )  -- called on read events
   540 				interface:_close()
   549 			--vdebug( "new client read event, id/ip/port:", tostring(interface.id), tostring(ip), tostring(port) )
   541 				interface.eventwrite = nil
   550 			if interface.noreading or interface.fatalerror then  -- leave this event
       
   551 				--vdebug( "leaving this event because:", tostring(interface.noreading or interface.fatalerror) )
       
   552 				interface.eventread = nil
   542 				return -1
   553 				return -1
   543 			end
   554 			end
   544 		end
       
   545 	end
       
   546 
       
   547 	interface.readcallback = function( event )  -- called on read events
       
   548 		--vdebug( "new client read event, id/ip/port:", tostring(interface.id), tostring(ip), tostring(port) )
       
   549 		if interface.noreading or interface.fatalerror then  -- leave this event
       
   550 			--vdebug( "leaving this event because:", tostring(interface.noreading or interface.fatalerror) )
       
   551 			interface.eventread = nil
       
   552 			return -1
       
   553 		end
       
   554 		if EV_TIMEOUT == event and interface:onreadtimeout() ~= true then
   555 		if EV_TIMEOUT == event and interface:onreadtimeout() ~= true then
   555 			return -1 -- took too long to get some data from client -> disconnect
   556 			return -1 -- took too long to get some data from client -> disconnect
   556 		end
   557 		end
   557 		if interface._usingssl then  -- handle luasec
   558 				if interface._usingssl then  -- handle luasec
   558 			if interface.eventwritetimeout then  -- ok, in the past writecallback was regged
   559 					if interface.eventwritetimeout then  -- ok, in the past writecallback was regged
   559 				local ret = interface.writecallback( )  -- call it
   560 						local ret = interface.writecallback( )  -- call it
   560 				--vdebug( "tried to write in readcallback, result:", tostring(ret) )
   561 						--vdebug( "tried to write in readcallback, result:", tostring(ret) )
   561 			end
   562 					end
   562 			if interface.eventreadtimeout then
   563 					if interface.eventreadtimeout then
   563 				interface.eventreadtimeout:close( )
   564 						interface.eventreadtimeout:close( )
   564 				interface.eventreadtimeout = nil
   565 						interface.eventreadtimeout = nil
   565 			end
   566 					end
   566 		end
   567 				end
   567 		local buffer, err, part = interface.conn:receive( interface._pattern )  -- receive buffer with "pattern"
   568 				local buffer, err, part = interface.conn:receive( interface._pattern )  -- receive buffer with "pattern"
   568 		--vdebug( "read data:", tostring(buffer), "error:", tostring(err), "part:", tostring(part) )
   569 				--vdebug( "read data:", tostring(buffer), "error:", tostring(err), "part:", tostring(part) )
   569 		buffer = buffer or part
   570 				buffer = buffer or part
   570 		if buffer and #buffer > cfg.MAX_READ_LENGTH then  -- check buffer length
   571 				if buffer and #buffer > cfg.MAX_READ_LENGTH then  -- check buffer length
   571 			interface.fatalerror = "receive buffer exceeded"
   572 					interface.fatalerror = "receive buffer exceeded"
   572 			debug( "fatal error:", interface.fatalerror )
   573 					debug( "fatal error:", interface.fatalerror )
   573 			interface:_close()
   574 					interface:_close()
   574 			interface.eventread = nil
   575 					interface.eventread = nil
   575 			return -1
   576 					return -1
   576 		end
   577 				end
   577 		if err and ( err ~= "timeout" and err ~= "wantread" ) then
   578 				if err and ( err ~= "timeout" and err ~= "wantread" ) then
   578 			if "wantwrite" == err then -- need to read on write event
   579 					if "wantwrite" == err then -- need to read on write event
   579 				if not interface.eventwrite then  -- register new write event if needed
   580 						if not interface.eventwrite then  -- register new write event if needed
   580 					interface.eventwrite = addevent( base, interface.conn, EV_WRITE, interface.writecallback, cfg.WRITE_TIMEOUT )
   581 							interface.eventwrite = addevent( base, interface.conn, EV_WRITE, interface.writecallback, cfg.WRITE_TIMEOUT )
   581 				end
   582 						end
   582 				interface.eventreadtimeout = addevent( base, nil, EV_TIMEOUT,
   583 						interface.eventreadtimeout = addevent( base, nil, EV_TIMEOUT,
   583 					function( )
   584 							function( )
       
   585 								interface:_close()
       
   586 							end, cfg.READ_TIMEOUT
       
   587 						)
       
   588 						debug( "wantwrite during read attempt, reg it in writecallback but dont know what really happens next..." )
       
   589 						-- to be honest i dont know what happens next, if it is allowed to first read, the write etc...
       
   590 					else  -- connection was closed or fatal error
       
   591 						interface.fatalerror = err
       
   592 						debug( "connection failed in read event:", interface.fatalerror )
   584 						interface:_close()
   593 						interface:_close()
   585 					end, cfg.READ_TIMEOUT
   594 						interface.eventread = nil
   586 				)
   595 						return -1
   587 				debug( "wantwrite during read attempt, reg it in writecallback but dont know what really happens next..." )
   596 					end
   588 				-- to be honest i dont know what happens next, if it is allowed to first read, the write etc...
   597 				else
   589 			else  -- connection was closed or fatal error
   598 					interface.onincoming( interface, buffer, err )  -- send new data to listener
   590 				interface.fatalerror = err
   599 				end
   591 				debug( "connection failed in read event:", interface.fatalerror )
   600 				if interface.noreading then
   592 				interface:_close()
   601 					interface.eventread = nil;
       
   602 					return -1;
       
   603 				end
       
   604 				return EV_READ, cfg.READ_TIMEOUT
       
   605 			end
       
   606 
       
   607 		client:settimeout( 0 )  -- set non blocking
       
   608 		setmetatable(interface, interface_mt)
       
   609 	interfacelist[ interface ] = true  -- add to interfacelist
       
   610 		return interface
       
   611 	end
       
   612 
       
   613 local function handleserver( server, addr, port, pattern, listener, sslctx )  -- creates an server interface
       
   614 		debug "creating server interface..."
       
   615 		local interface = {
       
   616 			_connections = 0;
       
   617 
       
   618 		type = "server";
       
   619 			conn = server;
       
   620 			onconnect = listener.onconnect;  -- will be called when new client connected
       
   621 			eventread = false;  -- read event handler
       
   622 			eventclose = false; -- close event handler
       
   623 			readcallback = false; -- read event callback
       
   624 			fatalerror = false; -- error message
       
   625 			nointerface = true;  -- lock/unlock parameter
       
   626 
       
   627 			_ip = addr, _port = port, _pattern = pattern,
       
   628 			_sslctx = sslctx;
       
   629 		}
       
   630 		interface.id = tostring(interface):match("%x+$");
       
   631 		interface.readcallback = function( event )  -- server handler, called on incoming connections
       
   632 			--vdebug( "server can accept, id/addr/port:", interface, addr, port )
       
   633 			if interface.fatalerror then
       
   634 				--vdebug( "leaving this event because:", self.fatalerror )
   593 				interface.eventread = nil
   635 				interface.eventread = nil
   594 				return -1
   636 				return -1
   595 			end
   637 			end
   596 		else
   638 			local delay = cfg.ACCEPT_DELAY
   597 			interface.onincoming( interface, buffer, err )  -- send new data to listener
   639 			if EV_TIMEOUT == event then
   598 		end
   640 				if interface._connections >= cfg.MAX_CONNECTIONS then  -- check connection count
   599 		if interface.noreading then
   641 					debug( "to many connections, seconds to wait for next accept:", delay )
   600 			interface.eventread = nil;
   642 					return EV_TIMEOUT, delay  -- timeout...
   601 			return -1;
   643 				else
   602 		end
   644 					return EV_READ  -- accept again
   603 		return EV_READ, cfg.READ_TIMEOUT
   645 				end
   604 	end
   646 			end
   605 
   647 			--vdebug("max connection check ok, accepting...")
   606 	client:settimeout( 0 )  -- set non blocking
   648 			local client, err = server:accept()    -- try to accept; TODO: check err
   607 	setmetatable(interface, interface_mt)
   649 			while client do
   608 	interfacelist[ interface ] = true  -- add to interfacelist
   650 				if interface._connections >= cfg.MAX_CONNECTIONS then
   609 	return interface
   651 					client:close( )  -- refuse connection
   610 end
   652 					debug( "maximal connections reached, refuse client connection; accept delay:", delay )
   611 
   653 					return EV_TIMEOUT, delay  -- delay for next accept attempt
   612 local function handleserver( server, addr, port, pattern, listener, sslctx )  -- creates an server interface
   654 				end
   613 	debug "creating server interface..."
   655 				local client_ip, client_port = client:getpeername( )
   614 	local interface = {
   656 				interface._connections = interface._connections + 1  -- increase connection count
   615 		_connections = 0;
   657 				local clientinterface = handleclient( client, client_ip, client_port, interface, pattern, listener, sslctx )
   616 
   658 				--vdebug( "client id:", clientinterface, "startssl:", startssl )
   617 		type = "server";
       
   618 		conn = server;
       
   619 		onconnect = listener.onconnect;  -- will be called when new client connected
       
   620 		eventread = false;  -- read event handler
       
   621 		eventclose = false; -- close event handler
       
   622 		readcallback = false; -- read event callback
       
   623 		fatalerror = false; -- error message
       
   624 		nointerface = true;  -- lock/unlock parameter
       
   625 
       
   626 		_ip = addr, _port = port, _pattern = pattern,
       
   627 		_sslctx = sslctx;
       
   628 	}
       
   629 	interface.id = tostring(interface):match("%x+$");
       
   630 	interface.readcallback = function( event )  -- server handler, called on incoming connections
       
   631 		--vdebug( "server can accept, id/addr/port:", interface, addr, port )
       
   632 		if interface.fatalerror then
       
   633 			--vdebug( "leaving this event because:", self.fatalerror )
       
   634 			interface.eventread = nil
       
   635 			return -1
       
   636 		end
       
   637 		local delay = cfg.ACCEPT_DELAY
       
   638 		if EV_TIMEOUT == event then
       
   639 			if interface._connections >= cfg.MAX_CONNECTIONS then  -- check connection count
       
   640 				debug( "to many connections, seconds to wait for next accept:", delay )
       
   641 				return EV_TIMEOUT, delay  -- timeout...
       
   642 			else
       
   643 				return EV_READ  -- accept again
       
   644 			end
       
   645 		end
       
   646 		--vdebug("max connection check ok, accepting...")
       
   647 		local client, err = server:accept()    -- try to accept; TODO: check err
       
   648 		while client do
       
   649 			if interface._connections >= cfg.MAX_CONNECTIONS then
       
   650 				client:close( )  -- refuse connection
       
   651 				debug( "maximal connections reached, refuse client connection; accept delay:", delay )
       
   652 				return EV_TIMEOUT, delay  -- delay for next accept attempt
       
   653 			end
       
   654 			local client_ip, client_port = client:getpeername( )
       
   655 			interface._connections = interface._connections + 1  -- increase connection count
       
   656 			local clientinterface = handleclient( client, client_ip, client_port, interface, pattern, listener, sslctx )
       
   657 			--vdebug( "client id:", clientinterface, "startssl:", startssl )
       
   658 			if has_luasec and sslctx then
   659 			if has_luasec and sslctx then
   659 				clientinterface:starttls(sslctx, true)
   660 					clientinterface:starttls(sslctx, true)
   660 			else
   661 				else
   661 				clientinterface:_start_session( true )
   662 					clientinterface:_start_session( true )
   662 			end
   663 				end
   663 			debug( "accepted incoming client connection from:", client_ip or "<unknown IP>", client_port or "<unknown port>", "to", port or "<unknown port>");
   664 				debug( "accepted incoming client connection from:", client_ip or "<unknown IP>", client_port or "<unknown port>", "to", port or "<unknown port>");
   664 
   665 
   665 			client, err = server:accept()    -- try to accept again
   666 				client, err = server:accept()    -- try to accept again
   666 		end
   667 			end
   667 		return EV_READ
   668 			return EV_READ
   668 	end
   669 		end
   669 
   670 
   670 	server:settimeout( 0 )
   671 		server:settimeout( 0 )
   671 	setmetatable(interface, interface_mt)
   672 		setmetatable(interface, interface_mt)
   672 	interfacelist[ interface ] = true
   673 	interfacelist[ interface ] = true
   673 	interface:_start_session()
   674 		interface:_start_session()
   674 	return interface
   675 		return interface
   675 end
   676 	end
   676 
   677 
   677 local function addserver( addr, port, listener, pattern, sslctx, startssl )  -- TODO: check arguments
   678 local function addserver( addr, port, listener, pattern, sslctx, startssl )  -- TODO: check arguments
   678 	--vdebug( "creating new tcp server with following parameters:", addr or "nil", port or "nil", sslctx or "nil", startssl or "nil")
   679 	--vdebug( "creating new tcp server with following parameters:", addr or "nil", port or "nil", sslctx or "nil", startssl or "nil")
   679 	if sslctx and not has_luasec then
   680 	if sslctx and not has_luasec then
   680 		debug "fatal error: luasec not found"
   681 		debug "fatal error: luasec not found"
   681 		return nil, "luasec not found"
   682 		return nil, "luasec not found"
   682 	end
       
   683 	local server, err = socket.bind( addr, port, cfg.ACCEPT_QUEUE )  -- create server socket
       
   684 	if not server then
       
   685 		debug( "creating server socket on "..addr.." port "..port.." failed:", err )
       
   686 		return nil, err
       
   687 	end
       
   688 	local interface = handleserver( server, addr, port, pattern, listener, sslctx, startssl )  -- new server handler
       
   689 	debug( "new server created with id:", tostring(interface))
       
   690 	return interface
       
   691 end
   683 end
       
   684 		local server, err = socket.bind( addr, port, cfg.ACCEPT_QUEUE )  -- create server socket
       
   685 		if not server then
       
   686 			debug( "creating server socket on "..addr.." port "..port.." failed:", err )
       
   687 			return nil, err
       
   688 		end
       
   689 		local interface = handleserver( server, addr, port, pattern, listener, sslctx, startssl )  -- new server handler
       
   690 		debug( "new server created with id:", tostring(interface))
       
   691 		return interface
       
   692 	end
   692 
   693 
   693 local function wrapclient( client, ip, port, listeners, pattern, sslctx )
   694 local function wrapclient( client, ip, port, listeners, pattern, sslctx )
   694 	local interface = handleclient( client, ip, port, nil, pattern, listeners, sslctx )
   695 		local interface = handleclient( client, ip, port, nil, pattern, listeners, sslctx )
   695 	interface:_start_connection(sslctx)
   696 		interface:_start_connection(sslctx)
   696 	return interface, client
   697 		return interface, client
   697 	--function handleclient( client, ip, port, server, pattern, listener, _, sslctx )  -- creates an client interface
   698 		--function handleclient( client, ip, port, server, pattern, listener, _, sslctx )  -- creates an client interface
   698 end
   699 	end
   699 
   700 
   700 local function addclient( addr, serverport, listener, pattern, sslctx, typ )
   701 local function addclient( addr, serverport, listener, pattern, sslctx, typ )
   701 	if sslctx and not has_luasec then
   702 	if sslctx and not has_luasec then
   702 		debug "need luasec, but not available"
   703 		debug "need luasec, but not available"
   703 		return nil, "luasec not found"
   704 		return nil, "luasec not found"
   704 	end
   705 		end
   705 	if not typ then
   706 	if not typ then
   706 		local addrinfo, err = getaddrinfo(addr)
   707 		local addrinfo, err = getaddrinfo(addr)
   707 		if not addrinfo then return nil, err end
   708 		if not addrinfo then return nil, err end
   708 		if addrinfo[1] and addrinfo[1].family == "inet6" then
   709 		if addrinfo[1] and addrinfo[1].family == "inet6" then
   709 			typ = "tcp6"
   710 			typ = "tcp6"
   710 		else
   711 		else
   711 			typ = "tcp"
   712 			typ = "tcp"
   712 		end
   713 			end
   713 	end
   714 		end
   714 	local create = socket[typ]
   715 	local create = socket[typ]
   715 	if type( create ) ~= "function"  then
   716 	if type( create ) ~= "function"  then
   716 		return nil, "invalid socket type"
   717 		return nil, "invalid socket type"
   717 	end
   718 			end
   718 	local client, err = create()  -- creating new socket
   719 	local client, err = create()  -- creating new socket
   719 	if not client then
   720 	if not client then
   720 		debug( "cannot create socket:", err )
   721 		debug( "cannot create socket:", err )
   721 		return nil, err
   722 				return nil, err
   722 	end
   723 			end
   723 	client:settimeout( 0 )  -- set nonblocking
   724 	client:settimeout( 0 )  -- set nonblocking
   724 	local res, err = client:connect( addr, serverport )  -- connect
   725 		local res, err = client:connect( addr, serverport )  -- connect
   725 	if res or ( err == "timeout" ) then
   726 		if res or ( err == "timeout" ) then
   726 		local ip, port = client:getsockname( )
   727 			local ip, port = client:getsockname( )
   727 		local interface = wrapclient( client, ip, serverport, listener, pattern, sslctx )
   728 		local interface = wrapclient( client, ip, serverport, listener, pattern, sslctx )
   728 		interface:_start_connection( sslctx )
   729 		interface:_start_connection( sslctx )
   729 		debug( "new connection id:", interface.id )
   730 			debug( "new connection id:", interface.id )
   730 		return interface, err
   731 			return interface, err
   731 	else
   732 		else
   732 		debug( "new connection failed:", err )
   733 			debug( "new connection failed:", err )
   733 		return nil, err
   734 			return nil, err
   734 	end
   735 		end
   735 end
   736 	end
   736 
   737 
   737 local function loop( )  -- starts the event loop
   738 local function loop( )  -- starts the event loop
   738 	base:loop( )
   739 	base:loop( )
   739 	return "quitting";
   740 	return "quitting";
   740 end
   741 end
   741 
   742 
   742 local function newevent( ... )
   743 local function newevent( ... )
   743 	return addevent( base, ... )
   744 	return addevent( base, ... )
   744 end
   745 	end
   745 
   746 
   746 local function closeallservers ( arg )
   747 local function closeallservers ( arg )
   747 	for item in pairs( interfacelist ) do
   748 	for item in pairs( interfacelist ) do
   748 		if item.type == "server" then
   749 		if item.type == "server" then
   749 			item:close( arg )
   750 			item:close( arg )
   751 	end
   752 	end
   752 end
   753 end
   753 
   754 
   754 local function setquitting(yes)
   755 local function setquitting(yes)
   755 	if yes then
   756 	if yes then
   756 		-- Quit now
   757 		 -- Quit now
   757 		closeallservers();
   758 		 closeallservers();
   758 		base:loopexit();
   759 		 base:loopexit();
   759 	end
   760 	end
   760 end
   761 end
   761 
   762 
   762 local function get_backend()
   763 local function get_backend()
   763 	return base:method();
   764 	return base:method();