PageRenderTime 39ms CodeModel.GetById 2ms app.highlight 28ms RepoModel.GetById 1ms app.codeStats 0ms

/net/server_select.lua

https://github.com/murnko/prosody
Lua | 1016 lines | 859 code | 115 blank | 42 comment | 110 complexity | d896f2dfcf3dd4410ff07c583da5c655 MD5 | raw file
   1--
   2-- server.lua by blastbeat of the luadch project
   3-- Re-used here under the MIT/X Consortium License
   4--
   5-- Modifications (C) 2008-2010 Matthew Wild, Waqas Hussain
   6--
   7
   8-- // wrapping luadch stuff // --
   9
  10local use = function( what )
  11	return _G[ what ]
  12end
  13
  14local log, table_concat = require ("util.logger").init("socket"), table.concat;
  15local out_put = function (...) return log("debug", table_concat{...}); end
  16local out_error = function (...) return log("warn", table_concat{...}); end
  17
  18----------------------------------// DECLARATION //--
  19
  20--// constants //--
  21
  22local STAT_UNIT = 1 -- byte
  23
  24--// lua functions //--
  25
  26local type = use "type"
  27local pairs = use "pairs"
  28local ipairs = use "ipairs"
  29local tonumber = use "tonumber"
  30local tostring = use "tostring"
  31
  32--// lua libs //--
  33
  34local os = use "os"
  35local table = use "table"
  36local string = use "string"
  37local coroutine = use "coroutine"
  38
  39--// lua lib methods //--
  40
  41local os_difftime = os.difftime
  42local math_min = math.min
  43local math_huge = math.huge
  44local table_concat = table.concat
  45local string_sub = string.sub
  46local coroutine_wrap = coroutine.wrap
  47local coroutine_yield = coroutine.yield
  48
  49--// extern libs //--
  50
  51local has_luasec, luasec = pcall ( require , "ssl" )
  52local luasocket = use "socket" or require "socket"
  53local luasocket_gettime = luasocket.gettime
  54local getaddrinfo = luasocket.dns.getaddrinfo
  55
  56--// extern lib methods //--
  57
  58local ssl_wrap = ( has_luasec and luasec.wrap )
  59local socket_bind = luasocket.bind
  60local socket_sleep = luasocket.sleep
  61local socket_select = luasocket.select
  62
  63--// functions //--
  64
  65local id
  66local loop
  67local stats
  68local idfalse
  69local closeall
  70local addsocket
  71local addserver
  72local addtimer
  73local getserver
  74local wrapserver
  75local getsettings
  76local closesocket
  77local removesocket
  78local removeserver
  79local wrapconnection
  80local changesettings
  81
  82--// tables //--
  83
  84local _server
  85local _readlist
  86local _timerlist
  87local _sendlist
  88local _socketlist
  89local _closelist
  90local _readtimes
  91local _writetimes
  92
  93--// simple data types //--
  94
  95local _
  96local _readlistlen
  97local _sendlistlen
  98local _timerlistlen
  99
 100local _sendtraffic
 101local _readtraffic
 102
 103local _selecttimeout
 104local _sleeptime
 105local _tcpbacklog
 106
 107local _starttime
 108local _currenttime
 109
 110local _maxsendlen
 111local _maxreadlen
 112
 113local _checkinterval
 114local _sendtimeout
 115local _readtimeout
 116
 117local _timer
 118
 119local _maxselectlen
 120local _maxfd
 121
 122local _maxsslhandshake
 123
 124----------------------------------// DEFINITION //--
 125
 126_server = { } -- key = port, value = table; list of listening servers
 127_readlist = { } -- array with sockets to read from
 128_sendlist = { } -- arrary with sockets to write to
 129_timerlist = { } -- array of timer functions
 130_socketlist = { } -- key = socket, value = wrapped socket (handlers)
 131_readtimes = { } -- key = handler, value = timestamp of last data reading
 132_writetimes = { } -- key = handler, value = timestamp of last data writing/sending
 133_closelist = { } -- handlers to close
 134
 135_readlistlen = 0 -- length of readlist
 136_sendlistlen = 0 -- length of sendlist
 137_timerlistlen = 0 -- lenght of timerlist
 138
 139_sendtraffic = 0 -- some stats
 140_readtraffic = 0
 141
 142_selecttimeout = 1 -- timeout of socket.select
 143_sleeptime = 0 -- time to wait at the end of every loop
 144_tcpbacklog = 128 -- some kind of hint to the OS
 145
 146_maxsendlen = 51000 * 1024 -- max len of send buffer
 147_maxreadlen = 25000 * 1024 -- max len of read buffer
 148
 149_checkinterval = 30 -- interval in secs to check idle clients
 150_sendtimeout = 60000 -- allowed send idle time in secs
 151_readtimeout = 6 * 60 * 60 -- allowed read idle time in secs
 152
 153local is_windows = package.config:sub(1,1) == "\\" -- check the directory separator, to detemine whether this is Windows
 154_maxfd = (is_windows and math.huge) or luasocket._SETSIZE or 1024 -- max fd number, limit to 1024 by default to prevent glibc buffer overflow, but not on Windows
 155_maxselectlen = luasocket._SETSIZE or 1024 -- But this still applies on Windows
 156
 157_maxsslhandshake = 30 -- max handshake round-trips
 158
 159----------------------------------// PRIVATE //--
 160
 161wrapserver = function( listeners, socket, ip, serverport, pattern, sslctx ) -- this function wraps a server -- FIXME Make sure FD < _maxfd
 162
 163	if socket:getfd() >= _maxfd then
 164		out_error("server.lua: Disallowed FD number: "..socket:getfd())
 165		socket:close()
 166		return nil, "fd-too-large"
 167	end
 168
 169	local connections = 0
 170
 171	local dispatch, disconnect = listeners.onconnect, listeners.ondisconnect
 172
 173	local accept = socket.accept
 174
 175	--// public methods of the object //--
 176
 177	local handler = { }
 178
 179	handler.shutdown = function( ) end
 180
 181	handler.ssl = function( )
 182		return sslctx ~= nil
 183	end
 184	handler.sslctx = function( )
 185		return sslctx
 186	end
 187	handler.remove = function( )
 188		connections = connections - 1
 189		if handler then
 190			handler.resume( )
 191		end
 192	end
 193	handler.close = function()
 194		socket:close( )
 195		_sendlistlen = removesocket( _sendlist, socket, _sendlistlen )
 196		_readlistlen = removesocket( _readlist, socket, _readlistlen )
 197		_server[ip..":"..serverport] = nil;
 198		_socketlist[ socket ] = nil
 199		handler = nil
 200		socket = nil
 201		--mem_free( )
 202		out_put "server.lua: closed server handler and removed sockets from list"
 203	end
 204	handler.pause = function( hard )
 205		if not handler.paused then
 206			_readlistlen = removesocket( _readlist, socket, _readlistlen )
 207			if hard then
 208				_socketlist[ socket ] = nil
 209				socket:close( )
 210				socket = nil;
 211			end
 212			handler.paused = true;
 213		end
 214	end
 215	handler.resume = function( )
 216		if handler.paused then
 217			if not socket then
 218				socket = socket_bind( ip, serverport, _tcpbacklog );
 219				socket:settimeout( 0 )
 220			end
 221			_readlistlen = addsocket(_readlist, socket, _readlistlen)
 222			_socketlist[ socket ] = handler
 223			handler.paused = false;
 224		end
 225	end
 226	handler.ip = function( )
 227		return ip
 228	end
 229	handler.serverport = function( )
 230		return serverport
 231	end
 232	handler.socket = function( )
 233		return socket
 234	end
 235	handler.readbuffer = function( )
 236		if _readlistlen >= _maxselectlen or _sendlistlen >= _maxselectlen then
 237			handler.pause( )
 238			out_put( "server.lua: refused new client connection: server full" )
 239			return false
 240		end
 241		local client, err = accept( socket )	-- try to accept
 242		if client then
 243			local ip, clientport = client:getpeername( )
 244			local handler, client, err = wrapconnection( handler, listeners, client, ip, serverport, clientport, pattern, sslctx ) -- wrap new client socket
 245			if err then -- error while wrapping ssl socket
 246				return false
 247			end
 248			connections = connections + 1
 249			out_put( "server.lua: accepted new client connection from ", tostring(ip), ":", tostring(clientport), " to ", tostring(serverport))
 250			if dispatch and not sslctx then -- SSL connections will notify onconnect when handshake completes
 251				return dispatch( handler );
 252			end
 253			return;
 254		elseif err then -- maybe timeout or something else
 255			out_put( "server.lua: error with new client connection: ", tostring(err) )
 256			return false
 257		end
 258	end
 259	return handler
 260end
 261
 262wrapconnection = function( server, listeners, socket, ip, serverport, clientport, pattern, sslctx ) -- this function wraps a client to a handler object
 263
 264	if socket:getfd() >= _maxfd then
 265		out_error("server.lua: Disallowed FD number: "..socket:getfd()) -- PROTIP: Switch to libevent
 266		socket:close( ) -- Should we send some kind of error here?
 267		if server then
 268			server.pause( )
 269		end
 270		return nil, nil, "fd-too-large"
 271	end
 272	socket:settimeout( 0 )
 273
 274	--// local import of socket methods //--
 275
 276	local send
 277	local receive
 278	local shutdown
 279
 280	--// private closures of the object //--
 281
 282	local ssl
 283
 284	local dispatch = listeners.onincoming
 285	local status = listeners.onstatus
 286	local disconnect = listeners.ondisconnect
 287	local drain = listeners.ondrain
 288	local onreadtimeout = listeners.onreadtimeout;
 289
 290	local bufferqueue = { } -- buffer array
 291	local bufferqueuelen = 0	-- end of buffer array
 292
 293	local toclose
 294	local fatalerror
 295	local needtls
 296
 297	local bufferlen = 0
 298
 299	local noread = false
 300	local nosend = false
 301
 302	local sendtraffic, readtraffic = 0, 0
 303
 304	local maxsendlen = _maxsendlen
 305	local maxreadlen = _maxreadlen
 306
 307	--// public methods of the object //--
 308
 309	local handler = bufferqueue -- saves a table ^_^
 310
 311	handler.dispatch = function( )
 312		return dispatch
 313	end
 314	handler.disconnect = function( )
 315		return disconnect
 316	end
 317	handler.onreadtimeout = onreadtimeout;
 318
 319	handler.setlistener = function( self, listeners )
 320		dispatch = listeners.onincoming
 321		disconnect = listeners.ondisconnect
 322		status = listeners.onstatus
 323		drain = listeners.ondrain
 324		handler.onreadtimeout = listeners.onreadtimeout
 325	end
 326	handler.getstats = function( )
 327		return readtraffic, sendtraffic
 328	end
 329	handler.ssl = function( )
 330		return ssl
 331	end
 332	handler.sslctx = function ( )
 333		return sslctx
 334	end
 335	handler.send = function( _, data, i, j )
 336		return send( socket, data, i, j )
 337	end
 338	handler.receive = function( pattern, prefix )
 339		return receive( socket, pattern, prefix )
 340	end
 341	handler.shutdown = function( pattern )
 342		return shutdown( socket, pattern )
 343	end
 344	handler.setoption = function (self, option, value)
 345		if socket.setoption then
 346			return socket:setoption(option, value);
 347		end
 348		return false, "setoption not implemented";
 349	end
 350	handler.force_close = function ( self, err )
 351		if bufferqueuelen ~= 0 then
 352			out_put("server.lua: discarding unwritten data for ", tostring(ip), ":", tostring(clientport))
 353			bufferqueuelen = 0;
 354		end
 355		return self:close(err);
 356	end
 357	handler.close = function( self, err )
 358		if not handler then return true; end
 359		_readlistlen = removesocket( _readlist, socket, _readlistlen )
 360		_readtimes[ handler ] = nil
 361		if bufferqueuelen ~= 0 then
 362			handler.sendbuffer() -- Try now to send any outstanding data
 363			if bufferqueuelen ~= 0 then -- Still not empty, so we'll try again later
 364				if handler then
 365					handler.write = nil -- ... but no further writing allowed
 366				end
 367				toclose = true
 368				return false
 369			end
 370		end
 371		if socket then
 372			_ = shutdown and shutdown( socket )
 373			socket:close( )
 374			_sendlistlen = removesocket( _sendlist, socket, _sendlistlen )
 375			_socketlist[ socket ] = nil
 376			socket = nil
 377		else
 378			out_put "server.lua: socket already closed"
 379		end
 380		if handler then
 381			_writetimes[ handler ] = nil
 382			_closelist[ handler ] = nil
 383			local _handler = handler;
 384			handler = nil
 385			if disconnect then
 386				disconnect(_handler, err or false);
 387				disconnect = nil
 388			end
 389		end
 390		if server then
 391			server.remove( )
 392		end
 393		out_put "server.lua: closed client handler and removed socket from list"
 394		return true
 395	end
 396	handler.ip = function( )
 397		return ip
 398	end
 399	handler.serverport = function( )
 400		return serverport
 401	end
 402	handler.clientport = function( )
 403		return clientport
 404	end
 405	handler.port = handler.clientport -- COMPAT server_event
 406	local write = function( self, data )
 407		bufferlen = bufferlen + #data
 408		if bufferlen > maxsendlen then
 409			_closelist[ handler ] = "send buffer exceeded"	 -- cannot close the client at the moment, have to wait to the end of the cycle
 410			handler.write = idfalse -- dont write anymore
 411			return false
 412		elseif socket and not _sendlist[ socket ] then
 413			_sendlistlen = addsocket(_sendlist, socket, _sendlistlen)
 414		end
 415		bufferqueuelen = bufferqueuelen + 1
 416		bufferqueue[ bufferqueuelen ] = data
 417		if handler then
 418			_writetimes[ handler ] = _writetimes[ handler ] or _currenttime
 419		end
 420		return true
 421	end
 422	handler.write = write
 423	handler.bufferqueue = function( self )
 424		return bufferqueue
 425	end
 426	handler.socket = function( self )
 427		return socket
 428	end
 429	handler.set_mode = function( self, new )
 430		pattern = new or pattern
 431		return pattern
 432	end
 433	handler.set_send = function ( self, newsend )
 434		send = newsend or send
 435		return send
 436	end
 437	handler.bufferlen = function( self, readlen, sendlen )
 438		maxsendlen = sendlen or maxsendlen
 439		maxreadlen = readlen or maxreadlen
 440		return bufferlen, maxreadlen, maxsendlen
 441	end
 442	--TODO: Deprecate
 443	handler.lock_read = function (self, switch)
 444		if switch == true then
 445			local tmp = _readlistlen
 446			_readlistlen = removesocket( _readlist, socket, _readlistlen )
 447			_readtimes[ handler ] = nil
 448			if _readlistlen ~= tmp then
 449				noread = true
 450			end
 451		elseif switch == false then
 452			if noread then
 453				noread = false
 454				_readlistlen = addsocket(_readlist, socket, _readlistlen)
 455				_readtimes[ handler ] = _currenttime
 456			end
 457		end
 458		return noread
 459	end
 460	handler.pause = function (self)
 461		return self:lock_read(true);
 462	end
 463	handler.resume = function (self)
 464		return self:lock_read(false);
 465	end
 466	handler.lock = function( self, switch )
 467		handler.lock_read (switch)
 468		if switch == true then
 469			handler.write = idfalse
 470			local tmp = _sendlistlen
 471			_sendlistlen = removesocket( _sendlist, socket, _sendlistlen )
 472			_writetimes[ handler ] = nil
 473			if _sendlistlen ~= tmp then
 474				nosend = true
 475			end
 476		elseif switch == false then
 477			handler.write = write
 478			if nosend then
 479				nosend = false
 480				write( "" )
 481			end
 482		end
 483		return noread, nosend
 484	end
 485	local _readbuffer = function( ) -- this function reads data
 486		local buffer, err, part = receive( socket, pattern )	-- receive buffer with "pattern"
 487		if not err or (err == "wantread" or err == "timeout") then -- received something
 488			local buffer = buffer or part or ""
 489			local len = #buffer
 490			if len > maxreadlen then
 491				handler:close( "receive buffer exceeded" )
 492				return false
 493			end
 494			local count = len * STAT_UNIT
 495			readtraffic = readtraffic + count
 496			_readtraffic = _readtraffic + count
 497			_readtimes[ handler ] = _currenttime
 498			--out_put( "server.lua: read data '", buffer:gsub("[^%w%p ]", "."), "', error: ", err )
 499			return dispatch( handler, buffer, err )
 500		else	-- connections was closed or fatal error
 501			out_put( "server.lua: client ", tostring(ip), ":", tostring(clientport), " read error: ", tostring(err) )
 502			fatalerror = true
 503			_ = handler and handler:force_close( err )
 504			return false
 505		end
 506	end
 507	local _sendbuffer = function( ) -- this function sends data
 508		local succ, err, byte, buffer, count;
 509		if socket then
 510			buffer = table_concat( bufferqueue, "", 1, bufferqueuelen )
 511			succ, err, byte = send( socket, buffer, 1, bufferlen )
 512			count = ( succ or byte or 0 ) * STAT_UNIT
 513			sendtraffic = sendtraffic + count
 514			_sendtraffic = _sendtraffic + count
 515			for i = bufferqueuelen,1,-1 do
 516				bufferqueue[ i ] = nil
 517			end
 518			--out_put( "server.lua: sended '", buffer, "', bytes: ", tostring(succ), ", error: ", tostring(err), ", part: ", tostring(byte), ", to: ", tostring(ip), ":", tostring(clientport) )
 519		else
 520			succ, err, count = false, "unexpected close", 0;
 521		end
 522		if succ then	-- sending succesful
 523			bufferqueuelen = 0
 524			bufferlen = 0
 525			_sendlistlen = removesocket( _sendlist, socket, _sendlistlen ) -- delete socket from writelist
 526			_writetimes[ handler ] = nil
 527			if drain then
 528				drain(handler)
 529			end
 530			_ = needtls and handler:starttls(nil)
 531			_ = toclose and handler:force_close( )
 532			return true
 533		elseif byte and ( err == "timeout" or err == "wantwrite" ) then -- want write
 534			buffer = string_sub( buffer, byte + 1, bufferlen ) -- new buffer
 535			bufferqueue[ 1 ] = buffer	 -- insert new buffer in queue
 536			bufferqueuelen = 1
 537			bufferlen = bufferlen - byte
 538			_writetimes[ handler ] = _currenttime
 539			return true
 540		else	-- connection was closed during sending or fatal error
 541			out_put( "server.lua: client ", tostring(ip), ":", tostring(clientport), " write error: ", tostring(err) )
 542			fatalerror = true
 543			_ = handler and handler:force_close( err )
 544			return false
 545		end
 546	end
 547
 548	-- Set the sslctx
 549	local handshake;
 550	function handler.set_sslctx(self, new_sslctx)
 551		sslctx = new_sslctx;
 552		local read, wrote
 553		handshake = coroutine_wrap( function( client ) -- create handshake coroutine
 554				local err
 555				for i = 1, _maxsslhandshake do
 556					_sendlistlen = ( wrote and removesocket( _sendlist, client, _sendlistlen ) ) or _sendlistlen
 557					_readlistlen = ( read and removesocket( _readlist, client, _readlistlen ) ) or _readlistlen
 558					read, wrote = nil, nil
 559					_, err = client:dohandshake( )
 560					if not err then
 561						out_put( "server.lua: ssl handshake done" )
 562						handler.readbuffer = _readbuffer	-- when handshake is done, replace the handshake function with regular functions
 563						handler.sendbuffer = _sendbuffer
 564						_ = status and status( handler, "ssl-handshake-complete" )
 565						if self.autostart_ssl and listeners.onconnect then
 566							listeners.onconnect(self);
 567						end
 568						_readlistlen = addsocket(_readlist, client, _readlistlen)
 569						return true
 570					else
 571						if err == "wantwrite" then
 572							_sendlistlen = addsocket(_sendlist, client, _sendlistlen)
 573							wrote = true
 574						elseif err == "wantread" then
 575							_readlistlen = addsocket(_readlist, client, _readlistlen)
 576							read = true
 577						else
 578							break;
 579						end
 580						err = nil;
 581						coroutine_yield( ) -- handshake not finished
 582					end
 583				end
 584				out_put( "server.lua: ssl handshake error: ", tostring(err or "handshake too long") )
 585				_ = handler and handler:force_close("ssl handshake failed")
 586				return false, err -- handshake failed
 587			end
 588		)
 589	end
 590	if has_luasec then
 591		handler.starttls = function( self, _sslctx)
 592			if _sslctx then
 593				handler:set_sslctx(_sslctx);
 594			end
 595			if bufferqueuelen > 0 then
 596				out_put "server.lua: we need to do tls, but delaying until send buffer empty"
 597				needtls = true
 598				return
 599			end
 600			out_put( "server.lua: attempting to start tls on " .. tostring( socket ) )
 601			local oldsocket, err = socket
 602			socket, err = ssl_wrap( socket, sslctx )	-- wrap socket
 603			if not socket then
 604				out_put( "server.lua: error while starting tls on client: ", tostring(err or "unknown error") )
 605				return nil, err -- fatal error
 606			end
 607
 608			socket:settimeout( 0 )
 609
 610			-- add the new socket to our system
 611			send = socket.send
 612			receive = socket.receive
 613			shutdown = id
 614			_socketlist[ socket ] = handler
 615			_readlistlen = addsocket(_readlist, socket, _readlistlen)
 616
 617			-- remove traces of the old socket
 618			_readlistlen = removesocket( _readlist, oldsocket, _readlistlen )
 619			_sendlistlen = removesocket( _sendlist, oldsocket, _sendlistlen )
 620			_socketlist[ oldsocket ] = nil
 621
 622			handler.starttls = nil
 623			needtls = nil
 624
 625			-- Secure now (if handshake fails connection will close)
 626			ssl = true
 627
 628			handler.readbuffer = handshake
 629			handler.sendbuffer = handshake
 630			return handshake( socket ) -- do handshake
 631		end
 632	end
 633
 634	handler.readbuffer = _readbuffer
 635	handler.sendbuffer = _sendbuffer
 636	send = socket.send
 637	receive = socket.receive
 638	shutdown = ( ssl and id ) or socket.shutdown
 639
 640	_socketlist[ socket ] = handler
 641	_readlistlen = addsocket(_readlist, socket, _readlistlen)
 642
 643	if sslctx and has_luasec then
 644		out_put "server.lua: auto-starting ssl negotiation..."
 645		handler.autostart_ssl = true;
 646		local ok, err = handler:starttls(sslctx);
 647		if ok == false then
 648			return nil, nil, err
 649		end
 650	end
 651
 652	return handler, socket
 653end
 654
 655id = function( )
 656end
 657
 658idfalse = function( )
 659	return false
 660end
 661
 662addsocket = function( list, socket, len )
 663	if not list[ socket ] then
 664		len = len + 1
 665		list[ len ] = socket
 666		list[ socket ] = len
 667	end
 668	return len;
 669end
 670
 671removesocket = function( list, socket, len )	-- this function removes sockets from a list ( copied from copas )
 672	local pos = list[ socket ]
 673	if pos then
 674		list[ socket ] = nil
 675		local last = list[ len ]
 676		list[ len ] = nil
 677		if last ~= socket then
 678			list[ last ] = pos
 679			list[ pos ] = last
 680		end
 681		return len - 1
 682	end
 683	return len
 684end
 685
 686closesocket = function( socket )
 687	_sendlistlen = removesocket( _sendlist, socket, _sendlistlen )
 688	_readlistlen = removesocket( _readlist, socket, _readlistlen )
 689	_socketlist[ socket ] = nil
 690	socket:close( )
 691	--mem_free( )
 692end
 693
 694local function link(sender, receiver, buffersize)
 695	local sender_locked;
 696	local _sendbuffer = receiver.sendbuffer;
 697	function receiver.sendbuffer()
 698		_sendbuffer();
 699		if sender_locked and receiver.bufferlen() < buffersize then
 700			sender:lock_read(false); -- Unlock now
 701			sender_locked = nil;
 702		end
 703	end
 704
 705	local _readbuffer = sender.readbuffer;
 706	function sender.readbuffer()
 707		_readbuffer();
 708		if not sender_locked and receiver.bufferlen() >= buffersize then
 709			sender_locked = true;
 710			sender:lock_read(true);
 711		end
 712	end
 713end
 714
 715----------------------------------// PUBLIC //--
 716
 717addserver = function( addr, port, listeners, pattern, sslctx ) -- this function provides a way for other scripts to reg a server
 718	addr = addr or "*"
 719	local err
 720	if type( listeners ) ~= "table" then
 721		err = "invalid listener table"
 722	elseif type ( addr ) ~= "string" then
 723		err = "invalid address"
 724	elseif type( port ) ~= "number" or not ( port >= 0 and port <= 65535 ) then
 725		err = "invalid port"
 726	elseif _server[ addr..":"..port ] then
 727		err = "listeners on '[" .. addr .. "]:" .. port .. "' already exist"
 728	elseif sslctx and not has_luasec then
 729		err = "luasec not found"
 730	end
 731	if err then
 732		out_error( "server.lua, [", addr, "]:", port, ": ", err )
 733		return nil, err
 734	end
 735	local server, err = socket_bind( addr, port, _tcpbacklog )
 736	if err then
 737		out_error( "server.lua, [", addr, "]:", port, ": ", err )
 738		return nil, err
 739	end
 740	local handler, err = wrapserver( listeners, server, addr, port, pattern, sslctx ) -- wrap new server socket
 741	if not handler then
 742		server:close( )
 743		return nil, err
 744	end
 745	server:settimeout( 0 )
 746	_readlistlen = addsocket(_readlist, server, _readlistlen)
 747	_server[ addr..":"..port ] = handler
 748	_socketlist[ server ] = handler
 749	out_put( "server.lua: new "..(sslctx and "ssl " or "").."server listener on '[", addr, "]:", port, "'" )
 750	return handler
 751end
 752
 753getserver = function ( addr, port )
 754	return _server[ addr..":"..port ];
 755end
 756
 757removeserver = function( addr, port )
 758	local handler = _server[ addr..":"..port ]
 759	if not handler then
 760		return nil, "no server found on '[" .. addr .. "]:" .. tostring( port ) .. "'"
 761	end
 762	handler:close( )
 763	_server[ addr..":"..port ] = nil
 764	return true
 765end
 766
 767closeall = function( )
 768	for _, handler in pairs( _socketlist ) do
 769		handler:close( )
 770		_socketlist[ _ ] = nil
 771	end
 772	_readlistlen = 0
 773	_sendlistlen = 0
 774	_timerlistlen = 0
 775	_server = { }
 776	_readlist = { }
 777	_sendlist = { }
 778	_timerlist = { }
 779	_socketlist = { }
 780	--mem_free( )
 781end
 782
 783getsettings = function( )
 784	return {
 785		select_timeout = _selecttimeout;
 786		select_sleep_time = _sleeptime;
 787		tcp_backlog = _tcpbacklog;
 788		max_send_buffer_size = _maxsendlen;
 789		max_receive_buffer_size = _maxreadlen;
 790		select_idle_check_interval = _checkinterval;
 791		send_timeout = _sendtimeout;
 792		read_timeout = _readtimeout;
 793		max_connections = _maxselectlen;
 794		max_ssl_handshake_roundtrips = _maxsslhandshake;
 795		highest_allowed_fd = _maxfd;
 796	}
 797end
 798
 799changesettings = function( new )
 800	if type( new ) ~= "table" then
 801		return nil, "invalid settings table"
 802	end
 803	_selecttimeout = tonumber( new.select_timeout ) or _selecttimeout
 804	_sleeptime = tonumber( new.select_sleep_time ) or _sleeptime
 805	_maxsendlen = tonumber( new.max_send_buffer_size ) or _maxsendlen
 806	_maxreadlen = tonumber( new.max_receive_buffer_size ) or _maxreadlen
 807	_checkinterval = tonumber( new.select_idle_check_interval ) or _checkinterval
 808	_tcpbacklog = tonumber( new.tcp_backlog ) or _tcpbacklog
 809	_sendtimeout = tonumber( new.send_timeout ) or _sendtimeout
 810	_readtimeout = tonumber( new.read_timeout ) or _readtimeout
 811	_maxselectlen = new.max_connections or _maxselectlen
 812	_maxsslhandshake = new.max_ssl_handshake_roundtrips or _maxsslhandshake
 813	_maxfd = new.highest_allowed_fd or _maxfd
 814	return true
 815end
 816
 817addtimer = function( listener )
 818	if type( listener ) ~= "function" then
 819		return nil, "invalid listener function"
 820	end
 821	_timerlistlen = _timerlistlen + 1
 822	_timerlist[ _timerlistlen ] = listener
 823	return true
 824end
 825
 826stats = function( )
 827	return _readtraffic, _sendtraffic, _readlistlen, _sendlistlen, _timerlistlen
 828end
 829
 830local quitting;
 831
 832local function setquitting(quit)
 833	quitting = not not quit;
 834end
 835
 836loop = function(once) -- this is the main loop of the program
 837	if quitting then return "quitting"; end
 838	if once then quitting = "once"; end
 839	local next_timer_time = math_huge;
 840	repeat
 841		local read, write, err = socket_select( _readlist, _sendlist, math_min(_selecttimeout, next_timer_time) )
 842		for i, socket in ipairs( write ) do -- send data waiting in writequeues
 843			local handler = _socketlist[ socket ]
 844			if handler then
 845				handler.sendbuffer( )
 846			else
 847				closesocket( socket )
 848				out_put "server.lua: found no handler and closed socket (writelist)"	-- this should not happen
 849			end
 850		end
 851		for i, socket in ipairs( read ) do -- receive data
 852			local handler = _socketlist[ socket ]
 853			if handler then
 854				handler.readbuffer( )
 855			else
 856				closesocket( socket )
 857				out_put "server.lua: found no handler and closed socket (readlist)" -- this can happen
 858			end
 859		end
 860		for handler, err in pairs( _closelist ) do
 861			handler.disconnect( )( handler, err )
 862			handler:force_close()	 -- forced disconnect
 863			_closelist[ handler ] = nil;
 864		end
 865		_currenttime = luasocket_gettime( )
 866
 867		-- Check for socket timeouts
 868		local difftime = os_difftime( _currenttime - _starttime )
 869		if difftime > _checkinterval then
 870			_starttime = _currenttime
 871			for handler, timestamp in pairs( _writetimes ) do
 872				if os_difftime( _currenttime - timestamp ) > _sendtimeout then
 873					handler.disconnect( )( handler, "send timeout" )
 874					handler:force_close()	 -- forced disconnect
 875				end
 876			end
 877			for handler, timestamp in pairs( _readtimes ) do
 878				if os_difftime( _currenttime - timestamp ) > _readtimeout then
 879					if not(handler.onreadtimeout) or handler:onreadtimeout() ~= true then
 880						handler.disconnect( )( handler, "read timeout" )
 881						handler:close( )	-- forced disconnect?
 882					end
 883				end
 884			end
 885		end
 886
 887		-- Fire timers
 888		if _currenttime - _timer >= math_min(next_timer_time, 1) then
 889			next_timer_time = math_huge;
 890			for i = 1, _timerlistlen do
 891				local t = _timerlist[ i ]( _currenttime ) -- fire timers
 892				if t then next_timer_time = math_min(next_timer_time, t); end
 893			end
 894			_timer = _currenttime
 895		else
 896			next_timer_time = next_timer_time - (_currenttime - _timer);
 897		end
 898
 899		-- wait some time (0 by default)
 900		socket_sleep( _sleeptime )
 901	until quitting;
 902	if once and quitting == "once" then quitting = nil; return; end
 903	return "quitting"
 904end
 905
 906local function step()
 907	return loop(true);
 908end
 909
 910local function get_backend()
 911	return "select";
 912end
 913
 914--// EXPERIMENTAL //--
 915
 916local wrapclient = function( socket, ip, serverport, listeners, pattern, sslctx )
 917	local handler, socket, err = wrapconnection( nil, listeners, socket, ip, serverport, "clientport", pattern, sslctx )
 918	if not handler then return nil, err end
 919	_socketlist[ socket ] = handler
 920	if not sslctx then
 921		_sendlistlen = addsocket(_sendlist, socket, _sendlistlen)
 922		if listeners.onconnect then
 923			-- When socket is writeable, call onconnect
 924			local _sendbuffer = handler.sendbuffer;
 925			handler.sendbuffer = function ()
 926				handler.sendbuffer = _sendbuffer;
 927				listeners.onconnect(handler);
 928				return _sendbuffer(); -- Send any queued outgoing data
 929			end
 930		end
 931	end
 932	return handler, socket
 933end
 934
 935local addclient = function( address, port, listeners, pattern, sslctx, typ )
 936	local err
 937	if type( listeners ) ~= "table" then
 938		err = "invalid listener table"
 939	elseif type ( address ) ~= "string" then
 940		err = "invalid address"
 941	elseif type( port ) ~= "number" or not ( port >= 0 and port <= 65535 ) then
 942		err = "invalid port"
 943	elseif sslctx and not has_luasec then
 944		err = "luasec not found"
 945	end
 946	if getaddrinfo and not typ then
 947		local addrinfo, err = getaddrinfo(address)
 948		if not addrinfo then return nil, err end
 949		if addrinfo[1] and addrinfo[1].family == "inet6" then
 950			typ = "tcp6"
 951		end
 952	end
 953	local create = luasocket[typ or "tcp"]
 954	if type( create ) ~= "function"  then
 955		err = "invalid socket type"
 956	end
 957
 958	if err then
 959		out_error( "server.lua, addclient: ", err )
 960		return nil, err
 961	end
 962
 963	local client, err = create( )
 964	if err then
 965		return nil, err
 966	end
 967	client:settimeout( 0 )
 968	local ok, err = client:connect( address, port )
 969	if ok or err == "timeout" then
 970		return wrapclient( client, address, port, listeners, pattern, sslctx )
 971	else
 972		return nil, err
 973	end
 974end
 975
 976--// EXPERIMENTAL //--
 977
 978----------------------------------// BEGIN //--
 979
 980use "setmetatable" ( _socketlist, { __mode = "k" } )
 981use "setmetatable" ( _readtimes, { __mode = "k" } )
 982use "setmetatable" ( _writetimes, { __mode = "k" } )
 983
 984_timer = luasocket_gettime( )
 985_starttime = luasocket_gettime( )
 986
 987local function setlogger(new_logger)
 988	local old_logger = log;
 989	if new_logger then
 990		log = new_logger;
 991	end
 992	return old_logger;
 993end
 994
 995----------------------------------// PUBLIC INTERFACE //--
 996
 997return {
 998	_addtimer = addtimer,
 999
1000	addclient = addclient,
1001	wrapclient = wrapclient,
1002
1003	loop = loop,
1004	link = link,
1005	step = step,
1006	stats = stats,
1007	closeall = closeall,
1008	addserver = addserver,
1009	getserver = getserver,
1010	setlogger = setlogger,
1011	getsettings = getsettings,
1012	setquitting = setquitting,
1013	removeserver = removeserver,
1014	get_backend = get_backend,
1015	changesettings = changesettings,
1016}