Comparison

net/server_select.lua @ 5331:ffa740b4f08d

net.server_select: Limit global number of sockets passed to select.
author Kim Alvefur <zash@zash.se>
date Tue, 12 Feb 2013 03:24:41 +0100
parent 5330:0a0ca2eb991b
child 5337:c22dd451487f
comparison
equal deleted inserted replaced
5330:0a0ca2eb991b 5331:ffa740b4f08d
120 120
121 local _cleanqueue 121 local _cleanqueue
122 122
123 local _timer 123 local _timer
124 124
125 local _maxclientsperserver 125 local _maxselectlen
126 local _maxfd
126 127
127 local _maxsslhandshake 128 local _maxsslhandshake
128 129
129 ----------------------------------// DEFINITION //-- 130 ----------------------------------// DEFINITION //--
130 131
154 _sendtimeout = 60000 -- allowed send idle time in secs 155 _sendtimeout = 60000 -- allowed send idle time in secs
155 _readtimeout = 6 * 60 * 60 -- allowed read idle time in secs 156 _readtimeout = 6 * 60 * 60 -- allowed read idle time in secs
156 157
157 _cleanqueue = false -- clean bufferqueue after using 158 _cleanqueue = false -- clean bufferqueue after using
158 159
159 _maxclientsperserver = 1000 160 _maxfd = luasocket._SETSIZE or 1024 -- We should ignore this on Windows. Perhaps by simply setting it to math.huge or something.
161 _maxselectlen = luasocket._SETSIZE or 1024 -- But this still applies on Windows
160 162
161 _maxsslhandshake = 30 -- max handshake round-trips 163 _maxsslhandshake = 30 -- max handshake round-trips
162 164
163 ----------------------------------// PRIVATE //-- 165 ----------------------------------// PRIVATE //--
164 166
165 wrapserver = function( listeners, socket, ip, serverport, pattern, sslctx, maxconnections ) -- this function wraps a server 167 wrapserver = function( listeners, socket, ip, serverport, pattern, sslctx ) -- this function wraps a server -- FIXME Make sure FD < _maxfd
166 168
167 maxconnections = maxconnections or _maxclientsperserver 169 if socket:getfd() >= _maxfd then
170 out_error("server.lua: Disallowed FD number: "..socket:getfd())
171 socket:close()
172 return nil, "fd-too-large"
173 end
168 174
169 local connections = 0 175 local connections = 0
170 176
171 local dispatch, disconnect = listeners.onconnect, listeners.ondisconnect 177 local dispatch, disconnect = listeners.onconnect, listeners.ondisconnect
172 178
231 end 237 end
232 handler.socket = function( ) 238 handler.socket = function( )
233 return socket 239 return socket
234 end 240 end
235 handler.readbuffer = function( ) 241 handler.readbuffer = function( )
236 if connections > maxconnections then 242 if _readlistlen >= _maxselectlen or _sendlistlen >= _maxselectlen then
237 handler.pause( ) 243 handler.pause( )
238 out_put( "server.lua: refused new client connection: server full" ) 244 out_put( "server.lua: refused new client connection: server full" )
239 return false 245 return false
240 end 246 end
241 local client, err = accept( socket ) -- try to accept 247 local client, err = accept( socket ) -- try to accept
259 return handler 265 return handler
260 end 266 end
261 267
262 wrapconnection = function( server, listeners, socket, ip, serverport, clientport, pattern, sslctx ) -- this function wraps a client to a handler object 268 wrapconnection = function( server, listeners, socket, ip, serverport, clientport, pattern, sslctx ) -- this function wraps a client to a handler object
263 269
270 if socket:getfd() >= _maxfd then
271 out_error("server.lua: Disallowed FD number: "..socket:getfd()) -- PROTIP: Switch to libevent
272 socket:close( ) -- Should we send some kind of error here?
273 server.pause( )
274 return nil, nil, "fd-too-large"
275 end
264 socket:settimeout( 0 ) 276 socket:settimeout( 0 )
265 277
266 --// local import of socket methods //-- 278 --// local import of socket methods //--
267 279
268 local send 280 local send
722 local server, err = socket_bind( addr, port ) 734 local server, err = socket_bind( addr, port )
723 if err then 735 if err then
724 out_error( "server.lua, [", addr, "]:", port, ": ", err ) 736 out_error( "server.lua, [", addr, "]:", port, ": ", err )
725 return nil, err 737 return nil, err
726 end 738 end
727 local handler, err = wrapserver( listeners, server, addr, port, pattern, sslctx, _maxclientsperserver ) -- wrap new server socket 739 local handler, err = wrapserver( listeners, server, addr, port, pattern, sslctx ) -- wrap new server socket
728 if not handler then 740 if not handler then
729 server:close( ) 741 server:close( )
730 return nil, err 742 return nil, err
731 end 743 end
732 server:settimeout( 0 ) 744 server:settimeout( 0 )
766 _socketlist = { } 778 _socketlist = { }
767 --mem_free( ) 779 --mem_free( )
768 end 780 end
769 781
770 getsettings = function( ) 782 getsettings = function( )
771 return _selecttimeout, _sleeptime, _maxsendlen, _maxreadlen, _checkinterval, _sendtimeout, _readtimeout, _cleanqueue, _maxclientsperserver, _maxsslhandshake 783 return _selecttimeout, _sleeptime, _maxsendlen, _maxreadlen, _checkinterval, _sendtimeout, _readtimeout, _cleanqueue, _maxselectlen, _maxsslhandshake, _maxfd
772 end 784 end
773 785
774 changesettings = function( new ) 786 changesettings = function( new )
775 if type( new ) ~= "table" then 787 if type( new ) ~= "table" then
776 return nil, "invalid settings table" 788 return nil, "invalid settings table"
781 _maxreadlen = tonumber( new.max_receive_buffer_size ) or _maxreadlen 793 _maxreadlen = tonumber( new.max_receive_buffer_size ) or _maxreadlen
782 _checkinterval = tonumber( new.select_idle_check_interval ) or _checkinterval 794 _checkinterval = tonumber( new.select_idle_check_interval ) or _checkinterval
783 _sendtimeout = tonumber( new.send_timeout ) or _sendtimeout 795 _sendtimeout = tonumber( new.send_timeout ) or _sendtimeout
784 _readtimeout = tonumber( new.read_timeout ) or _readtimeout 796 _readtimeout = tonumber( new.read_timeout ) or _readtimeout
785 _cleanqueue = new.select_clean_queue 797 _cleanqueue = new.select_clean_queue
786 _maxclientsperserver = new.max_connections or _maxclientsperserver 798 _maxselectlen = new.max_connections or _maxselectlen
787 _maxsslhandshake = new.max_ssl_handshake_roundtrips or _maxsslhandshake 799 _maxsslhandshake = new.max_ssl_handshake_roundtrips or _maxsslhandshake
800 _maxfd = new.highest_allowed_fd or _maxfd
788 return true 801 return true
789 end 802 end
790 803
791 addtimer = function( listener ) 804 addtimer = function( listener )
792 if type( listener ) ~= "function" then 805 if type( listener ) ~= "function" then
863 end 876 end
864 877
865 --// EXPERIMENTAL //-- 878 --// EXPERIMENTAL //--
866 879
867 local wrapclient = function( socket, ip, serverport, listeners, pattern, sslctx ) 880 local wrapclient = function( socket, ip, serverport, listeners, pattern, sslctx )
868 local handler = wrapconnection( nil, listeners, socket, ip, serverport, "clientport", pattern, sslctx ) 881 local handler, socket, err = wrapconnection( nil, listeners, socket, ip, serverport, "clientport", pattern, sslctx )
882 if not handler then return nil, err end
869 _socketlist[ socket ] = handler 883 _socketlist[ socket ] = handler
870 if not sslctx then 884 if not sslctx then
871 _sendlistlen = addsocket(_sendlist, socket, _sendlistlen) 885 _sendlistlen = addsocket(_sendlist, socket, _sendlistlen)
872 if listeners.onconnect then 886 if listeners.onconnect then
873 -- When socket is writeable, call onconnect 887 -- When socket is writeable, call onconnect