Comparison

net/server_select.lua @ 2581:1b9f424e695e

net.server_select: *Major* whitespace refactoring to meet Prosody's coding style guidelines, we now have tabs
author Matthew Wild <mwild1@gmail.com>
date Wed, 10 Feb 2010 19:12:43 +0000
parent 2559:a90a00ebae25
child 2582:d6afb6d919df
comparison
equal deleted inserted replaced
2580:61f0acd9086f 2581:1b9f424e695e
6 -- 6 --
7 7
8 -- // wrapping luadch stuff // -- 8 -- // wrapping luadch stuff // --
9 9
10 local use = function( what ) 10 local use = function( what )
11 return _G[ what ] 11 return _G[ what ]
12 end 12 end
13 local clean = function( tbl ) 13 local clean = function( tbl )
14 for i, k in pairs( tbl ) do 14 for i, k in pairs( tbl ) do
15 tbl[ i ] = nil 15 tbl[ i ] = nil
16 end 16 end
17 end 17 end
18 18
19 local log, table_concat = require ("util.logger").init("socket"), table.concat; 19 local log, table_concat = require ("util.logger").init("socket"), table.concat;
20 local out_put = function (...) return log("debug", table_concat{...}); end 20 local out_put = function (...) return log("debug", table_concat{...}); end
21 local out_error = function (...) return log("warn", table_concat{...}); end 21 local out_error = function (...) return log("warn", table_concat{...}); end
23 23
24 ----------------------------------// DECLARATION //-- 24 ----------------------------------// DECLARATION //--
25 25
26 --// constants //-- 26 --// constants //--
27 27
28 local STAT_UNIT = 1 -- byte 28 local STAT_UNIT = 1 -- byte
29 29
30 --// lua functions //-- 30 --// lua functions //--
31 31
32 local type = use "type" 32 local type = use "type"
33 local pairs = use "pairs" 33 local pairs = use "pairs"
125 125
126 local _maxclientsperserver 126 local _maxclientsperserver
127 127
128 ----------------------------------// DEFINITION //-- 128 ----------------------------------// DEFINITION //--
129 129
130 _server = { } -- key = port, value = table; list of listening servers 130 _server = { } -- key = port, value = table; list of listening servers
131 _readlist = { } -- array with sockets to read from 131 _readlist = { } -- array with sockets to read from
132 _sendlist = { } -- arrary with sockets to write to 132 _sendlist = { } -- arrary with sockets to write to
133 _timerlist = { } -- array of timer functions 133 _timerlist = { } -- array of timer functions
134 _socketlist = { } -- key = socket, value = wrapped socket (handlers) 134 _socketlist = { } -- key = socket, value = wrapped socket (handlers)
135 _readtimes = { } -- key = handler, value = timestamp of last data reading 135 _readtimes = { } -- key = handler, value = timestamp of last data reading
136 _writetimes = { } -- key = handler, value = timestamp of last data writing/sending 136 _writetimes = { } -- key = handler, value = timestamp of last data writing/sending
137 _closelist = { } -- handlers to close 137 _closelist = { } -- handlers to close
138 138
139 _readlistlen = 0 -- length of readlist 139 _readlistlen = 0 -- length of readlist
140 _sendlistlen = 0 -- length of sendlist 140 _sendlistlen = 0 -- length of sendlist
141 _timerlistlen = 0 -- lenght of timerlist 141 _timerlistlen = 0 -- lenght of timerlist
142 142
143 _sendtraffic = 0 -- some stats 143 _sendtraffic = 0 -- some stats
144 _readtraffic = 0 144 _readtraffic = 0
145 145
146 _selecttimeout = 1 -- timeout of socket.select 146 _selecttimeout = 1 -- timeout of socket.select
147 _sleeptime = 0 -- time to wait at the end of every loop 147 _sleeptime = 0 -- time to wait at the end of every loop
148 148
149 _maxsendlen = 51000 * 1024 -- max len of send buffer 149 _maxsendlen = 51000 * 1024 -- max len of send buffer
150 _maxreadlen = 25000 * 1024 -- max len of read buffer 150 _maxreadlen = 25000 * 1024 -- max len of read buffer
151 151
152 _checkinterval = 1200000 -- interval in secs to check idle clients 152 _checkinterval = 1200000 -- interval in secs to check idle clients
153 _sendtimeout = 60000 -- allowed send idle time in secs 153 _sendtimeout = 60000 -- allowed send idle time in secs
154 _readtimeout = 6 * 60 * 60 -- allowed read idle time in secs 154 _readtimeout = 6 * 60 * 60 -- allowed read idle time in secs
155 155
156 _cleanqueue = false -- clean bufferqueue after using 156 _cleanqueue = false -- clean bufferqueue after using
157 157
158 _maxclientsperserver = 1000 158 _maxclientsperserver = 1000
159 159
160 _maxsslhandshake = 30 -- max handshake round-trips 160 _maxsslhandshake = 30 -- max handshake round-trips
161
161 ----------------------------------// PRIVATE //-- 162 ----------------------------------// PRIVATE //--
162 163
163 wrapserver = function( listeners, socket, ip, serverport, pattern, sslctx, maxconnections ) -- this function wraps a server 164 wrapserver = function( listeners, socket, ip, serverport, pattern, sslctx, maxconnections ) -- this function wraps a server
164 165
165 maxconnections = maxconnections or _maxclientsperserver 166 maxconnections = maxconnections or _maxclientsperserver
166 167
167 local connections = 0 168 local connections = 0
168 169
169 local dispatch, disconnect = listeners.onincoming, listeners.ondisconnect 170 local dispatch, disconnect = listeners.onincoming, listeners.ondisconnect
170 171
171 local accept = socket.accept 172 local accept = socket.accept
172 173
173 --// public methods of the object //-- 174 --// public methods of the object //--
174 175
175 local handler = { } 176 local handler = { }
176 177
177 handler.shutdown = function( ) end 178 handler.shutdown = function( ) end
178 179
179 handler.ssl = function( ) 180 handler.ssl = function( )
180 return sslctx ~= nil 181 return sslctx ~= nil
181 end 182 end
182 handler.sslctx = function( ) 183 handler.sslctx = function( )
183 return sslctx 184 return sslctx
184 end 185 end
185 handler.remove = function( ) 186 handler.remove = function( )
186 connections = connections - 1 187 connections = connections - 1
187 end 188 end
188 handler.close = function( ) 189 handler.close = function( )
189 for _, handler in pairs( _socketlist ) do 190 for _, handler in pairs( _socketlist ) do
190 if handler.serverport == serverport then 191 if handler.serverport == serverport then
191 handler.disconnect( handler, "server closed" ) 192 handler.disconnect( handler, "server closed" )
192 handler:close( true ) 193 handler:close( true )
193 end 194 end
194 end 195 end
195 socket:close( ) 196 socket:close( )
196 _sendlistlen = removesocket( _sendlist, socket, _sendlistlen ) 197 _sendlistlen = removesocket( _sendlist, socket, _sendlistlen )
197 _readlistlen = removesocket( _readlist, socket, _readlistlen ) 198 _readlistlen = removesocket( _readlist, socket, _readlistlen )
198 _socketlist[ socket ] = nil 199 _socketlist[ socket ] = nil
199 handler = nil 200 handler = nil
200 socket = nil 201 socket = nil
201 --mem_free( ) 202 --mem_free( )
202 out_put "server.lua: closed server handler and removed sockets from list" 203 out_put "server.lua: closed server handler and removed sockets from list"
203 end 204 end
204 handler.ip = function( ) 205 handler.ip = function( )
205 return ip 206 return ip
206 end 207 end
207 handler.serverport = function( ) 208 handler.serverport = function( )
208 return serverport 209 return serverport
209 end 210 end
210 handler.socket = function( ) 211 handler.socket = function( )
211 return socket 212 return socket
212 end 213 end
213 handler.readbuffer = function( ) 214 handler.readbuffer = function( )
214 if connections > maxconnections then 215 if connections > maxconnections then
215 out_put( "server.lua: refused new client connection: server full" ) 216 out_put( "server.lua: refused new client connection: server full" )
216 return false 217 return false
217 end 218 end
218 local client, err = accept( socket ) -- try to accept 219 local client, err = accept( socket ) -- try to accept
219 if client then 220 if client then
220 local ip, clientport = client:getpeername( ) 221 local ip, clientport = client:getpeername( )
221 client:settimeout( 0 ) 222 client:settimeout( 0 )
222 local handler, client, err = wrapconnection( handler, listeners, client, ip, serverport, clientport, pattern, sslctx ) -- wrap new client socket 223 local handler, client, err = wrapconnection( handler, listeners, client, ip, serverport, clientport, pattern, sslctx ) -- wrap new client socket
223 if err then -- error while wrapping ssl socket 224 if err then -- error while wrapping ssl socket
224 return false 225 return false
225 end 226 end
226 connections = connections + 1 227 connections = connections + 1
227 out_put( "server.lua: accepted new client connection from ", tostring(ip), ":", tostring(clientport), " to ", tostring(serverport)) 228 out_put( "server.lua: accepted new client connection from ", tostring(ip), ":", tostring(clientport), " to ", tostring(serverport))
228 return dispatch( handler ) 229 return dispatch( handler )
229 elseif err then -- maybe timeout or something else 230 elseif err then -- maybe timeout or something else
230 out_put( "server.lua: error with new client connection: ", tostring(err) ) 231 out_put( "server.lua: error with new client connection: ", tostring(err) )
231 return false 232 return false
232 end 233 end
233 end 234 end
234 return handler 235 return handler
235 end 236 end
236 237
237 wrapconnection = function( server, listeners, socket, ip, serverport, clientport, pattern, sslctx ) -- this function wraps a client to a handler object 238 wrapconnection = function( server, listeners, socket, ip, serverport, clientport, pattern, sslctx ) -- this function wraps a client to a handler object
238 239
239 socket:settimeout( 0 ) 240 socket:settimeout( 0 )
240 241
241 --// local import of socket methods //-- 242 --// local import of socket methods //--
242 243
243 local send 244 local send
244 local receive 245 local receive
245 local shutdown 246 local shutdown
246 247
247 --// private closures of the object //-- 248 --// private closures of the object //--
248 249
249 local ssl 250 local ssl
250 251
251 local dispatch = listeners.onincoming 252 local dispatch = listeners.onincoming
252 local status = listeners.onstatus 253 local status = listeners.onstatus
253 local disconnect = listeners.ondisconnect 254 local disconnect = listeners.ondisconnect
254 255
255 local bufferqueue = { } -- buffer array 256 local bufferqueue = { } -- buffer array
256 local bufferqueuelen = 0 -- end of buffer array 257 local bufferqueuelen = 0 -- end of buffer array
257 258
258 local toclose 259 local toclose
259 local fatalerror 260 local fatalerror
260 local needtls 261 local needtls
261 262
262 local bufferlen = 0 263 local bufferlen = 0
263 264
264 local noread = false 265 local noread = false
265 local nosend = false 266 local nosend = false
266 267
267 local sendtraffic, readtraffic = 0, 0 268 local sendtraffic, readtraffic = 0, 0
268 269
269 local maxsendlen = _maxsendlen 270 local maxsendlen = _maxsendlen
270 local maxreadlen = _maxreadlen 271 local maxreadlen = _maxreadlen
271 272
272 --// public methods of the object //-- 273 --// public methods of the object //--
273 274
274 local handler = bufferqueue -- saves a table ^_^ 275 local handler = bufferqueue -- saves a table ^_^
275 276
276 handler.dispatch = function( ) 277 handler.dispatch = function( )
277 return dispatch 278 return dispatch
278 end 279 end
279 handler.disconnect = function( ) 280 handler.disconnect = function( )
280 return disconnect 281 return disconnect
281 end 282 end
282 handler.setlistener = function( self, listeners ) 283 handler.setlistener = function( self, listeners )
283 dispatch = listeners.onincoming 284 dispatch = listeners.onincoming
284 disconnect = listeners.ondisconnect 285 disconnect = listeners.ondisconnect
285 status = listeners.onstatus 286 status = listeners.onstatus
286 end 287 end
287 handler.getstats = function( ) 288 handler.getstats = function( )
288 return readtraffic, sendtraffic 289 return readtraffic, sendtraffic
289 end 290 end
290 handler.ssl = function( ) 291 handler.ssl = function( )
291 return ssl 292 return ssl
292 end 293 end
293 handler.sslctx = function ( ) 294 handler.sslctx = function ( )
294 return sslctx 295 return sslctx
295 end 296 end
296 handler.send = function( _, data, i, j ) 297 handler.send = function( _, data, i, j )
297 return send( socket, data, i, j ) 298 return send( socket, data, i, j )
298 end 299 end
299 handler.receive = function( pattern, prefix ) 300 handler.receive = function( pattern, prefix )
300 return receive( socket, pattern, prefix ) 301 return receive( socket, pattern, prefix )
301 end 302 end
302 handler.shutdown = function( pattern ) 303 handler.shutdown = function( pattern )
303 return shutdown( socket, pattern ) 304 return shutdown( socket, pattern )
304 end 305 end
305 handler.setoption = function (self, option, value) 306 handler.setoption = function (self, option, value)
306 if socket.setoption then 307 if socket.setoption then
307 return socket:setoption(option, value); 308 return socket:setoption(option, value);
308 end 309 end
309 return false, "setoption not implemented"; 310 return false, "setoption not implemented";
310 end 311 end
311 handler.close = function( self, forced ) 312 handler.close = function( self, forced )
312 if not handler then return true; end 313 if not handler then return true; end
313 _readlistlen = removesocket( _readlist, socket, _readlistlen ) 314 _readlistlen = removesocket( _readlist, socket, _readlistlen )
314 _readtimes[ handler ] = nil 315 _readtimes[ handler ] = nil
315 if bufferqueuelen ~= 0 then 316 if bufferqueuelen ~= 0 then
316 if not ( forced or fatalerror ) then 317 if not ( forced or fatalerror ) then
317 handler.sendbuffer( ) 318 handler.sendbuffer( )
318 if bufferqueuelen ~= 0 then -- try again... 319 if bufferqueuelen ~= 0 then -- try again...
319 if handler then 320 if handler then
320 handler.write = nil -- ... but no further writing allowed 321 handler.write = nil -- ... but no further writing allowed
321 end 322 end
322 toclose = true 323 toclose = true
323 return false 324 return false
324 end 325 end
325 else 326 else
326 send( socket, table_concat( bufferqueue, "", 1, bufferqueuelen ), 1, bufferlen ) -- forced send 327 send( socket, table_concat( bufferqueue, "", 1, bufferqueuelen ), 1, bufferlen ) -- forced send
327 end 328 end
328 end 329 end
329 if socket then 330 if socket then
330 _ = shutdown and shutdown( socket ) 331 _ = shutdown and shutdown( socket )
331 socket:close( ) 332 socket:close( )
332 _sendlistlen = removesocket( _sendlist, socket, _sendlistlen ) 333 _sendlistlen = removesocket( _sendlist, socket, _sendlistlen )
333 _socketlist[ socket ] = nil 334 _socketlist[ socket ] = nil
334 socket = nil 335 socket = nil
335 else 336 else
336 out_put "server.lua: socket already closed" 337 out_put "server.lua: socket already closed"
337 end 338 end
338 if handler then 339 if handler then
339 _writetimes[ handler ] = nil 340 _writetimes[ handler ] = nil
340 _closelist[ handler ] = nil 341 _closelist[ handler ] = nil
341 handler = nil 342 handler = nil
342 end 343 end
343 if server then 344 if server then
344 server.remove( ) 345 server.remove( )
345 end 346 end
346 out_put "server.lua: closed client handler and removed socket from list" 347 out_put "server.lua: closed client handler and removed socket from list"
347 return true 348 return true
348 end 349 end
349 handler.ip = function( ) 350 handler.ip = function( )
350 return ip 351 return ip
351 end 352 end
352 handler.serverport = function( ) 353 handler.serverport = function( )
353 return serverport 354 return serverport
354 end 355 end
355 handler.clientport = function( ) 356 handler.clientport = function( )
356 return clientport 357 return clientport
357 end 358 end
358 local write = function( self, data ) 359 local write = function( self, data )
359 bufferlen = bufferlen + string_len( data ) 360 bufferlen = bufferlen + string_len( data )
360 if bufferlen > maxsendlen then 361 if bufferlen > maxsendlen then
361 _closelist[ handler ] = "send buffer exceeded" -- cannot close the client at the moment, have to wait to the end of the cycle 362 _closelist[ handler ] = "send buffer exceeded" -- cannot close the client at the moment, have to wait to the end of the cycle
362 handler.write = idfalse -- dont write anymore 363 handler.write = idfalse -- dont write anymore
363 return false 364 return false
364 elseif socket and not _sendlist[ socket ] then 365 elseif socket and not _sendlist[ socket ] then
365 _sendlistlen = addsocket(_sendlist, socket, _sendlistlen) 366 _sendlistlen = addsocket(_sendlist, socket, _sendlistlen)
366 end 367 end
367 bufferqueuelen = bufferqueuelen + 1 368 bufferqueuelen = bufferqueuelen + 1
368 bufferqueue[ bufferqueuelen ] = data 369 bufferqueue[ bufferqueuelen ] = data
369 if handler then 370 if handler then
370 _writetimes[ handler ] = _writetimes[ handler ] or _currenttime 371 _writetimes[ handler ] = _writetimes[ handler ] or _currenttime
371 end 372 end
372 return true 373 return true
373 end 374 end
374 handler.write = write 375 handler.write = write
375 handler.bufferqueue = function( self ) 376 handler.bufferqueue = function( self )
376 return bufferqueue 377 return bufferqueue
377 end 378 end
378 handler.socket = function( self ) 379 handler.socket = function( self )
379 return socket 380 return socket
380 end 381 end
381 handler.pattern = function( self, new ) 382 handler.pattern = function( self, new )
382 pattern = new or pattern 383 pattern = new or pattern
383 return pattern 384 return pattern
384 end 385 end
385 handler.set_send = function ( self, newsend ) 386 handler.set_send = function ( self, newsend )
386 send = newsend or send 387 send = newsend or send
387 return send 388 return send
388 end 389 end
389 handler.bufferlen = function( self, readlen, sendlen ) 390 handler.bufferlen = function( self, readlen, sendlen )
390 maxsendlen = sendlen or maxsendlen 391 maxsendlen = sendlen or maxsendlen
391 maxreadlen = readlen or maxreadlen 392 maxreadlen = readlen or maxreadlen
392 return bufferlen, maxreadlen, maxsendlen 393 return bufferlen, maxreadlen, maxsendlen
393 end 394 end
394 handler.lock_read = function (self, switch) 395 handler.lock_read = function (self, switch)
395 if switch == true then 396 if switch == true then
396 local tmp = _readlistlen 397 local tmp = _readlistlen
397 _readlistlen = removesocket( _readlist, socket, _readlistlen ) 398 _readlistlen = removesocket( _readlist, socket, _readlistlen )
398 _readtimes[ handler ] = nil 399 _readtimes[ handler ] = nil
399 if _readlistlen ~= tmp then 400 if _readlistlen ~= tmp then
400 noread = true 401 noread = true
401 end 402 end
402 elseif switch == false then 403 elseif switch == false then
403 if noread then 404 if noread then
404 noread = false 405 noread = false
405 _readlistlen = addsocket(_readlist, socket, _readlistlen) 406 _readlistlen = addsocket(_readlist, socket, _readlistlen)
406 _readtimes[ handler ] = _currenttime 407 _readtimes[ handler ] = _currenttime
407 end 408 end
408 end 409 end
409 return noread 410 return noread
410 end 411 end
411 handler.lock = function( self, switch ) 412 handler.lock = function( self, switch )
412 handler.lock_read (switch) 413 handler.lock_read (switch)
413 if switch == true then 414 if switch == true then
414 handler.write = idfalse 415 handler.write = idfalse
415 local tmp = _sendlistlen 416 local tmp = _sendlistlen
416 _sendlistlen = removesocket( _sendlist, socket, _sendlistlen ) 417 _sendlistlen = removesocket( _sendlist, socket, _sendlistlen )
417 _writetimes[ handler ] = nil 418 _writetimes[ handler ] = nil
418 if _sendlistlen ~= tmp then 419 if _sendlistlen ~= tmp then
419 nosend = true 420 nosend = true
420 end 421 end
421 elseif switch == false then 422 elseif switch == false then
422 handler.write = write 423 handler.write = write
423 if nosend then 424 if nosend then
424 nosend = false 425 nosend = false
425 write( "" ) 426 write( "" )
426 end 427 end
427 end 428 end
428 return noread, nosend 429 return noread, nosend
429 end 430 end
430 local _readbuffer = function( ) -- this function reads data 431 local _readbuffer = function( ) -- this function reads data
431 local buffer, err, part = receive( socket, pattern ) -- receive buffer with "pattern" 432 local buffer, err, part = receive( socket, pattern ) -- receive buffer with "pattern"
432 if not err or (err == "wantread" or err == "timeout") or string_len(part) > 0 then -- received something 433 if not err or (err == "wantread" or err == "timeout") or string_len(part) > 0 then -- received something
433 local buffer = buffer or part or "" 434 local buffer = buffer or part or ""
434 local len = string_len( buffer ) 435 local len = string_len( buffer )
435 if len > maxreadlen then 436 if len > maxreadlen then
436 disconnect( handler, "receive buffer exceeded" ) 437 disconnect( handler, "receive buffer exceeded" )
437 handler.close( true ) 438 handler.close( true )
438 return false 439 return false
439 end 440 end
440 local count = len * STAT_UNIT 441 local count = len * STAT_UNIT
441 readtraffic = readtraffic + count 442 readtraffic = readtraffic + count
442 _readtraffic = _readtraffic + count 443 _readtraffic = _readtraffic + count
443 _readtimes[ handler ] = _currenttime 444 _readtimes[ handler ] = _currenttime
444 --out_put( "server.lua: read data '", buffer:gsub("[^%w%p ]", "."), "', error: ", err ) 445 --out_put( "server.lua: read data '", buffer:gsub("[^%w%p ]", "."), "', error: ", err )
445 return dispatch( handler, buffer, err ) 446 return dispatch( handler, buffer, err )
446 else -- connections was closed or fatal error 447 else -- connections was closed or fatal error
447 out_put( "server.lua: client ", tostring(ip), ":", tostring(clientport), " read error: ", tostring(err) ) 448 out_put( "server.lua: client ", tostring(ip), ":", tostring(clientport), " read error: ", tostring(err) )
448 fatalerror = true 449 fatalerror = true
449 disconnect( handler, err ) 450 disconnect( handler, err )
450 _ = handler and handler.close( ) 451 _ = handler and handler.close( )
451 return false 452 return false
452 end 453 end
453 end 454 end
454 local _sendbuffer = function( ) -- this function sends data 455 local _sendbuffer = function( ) -- this function sends data
455 local succ, err, byte, buffer, count; 456 local succ, err, byte, buffer, count;
456 local count; 457 local count;
457 if socket then 458 if socket then
458 buffer = table_concat( bufferqueue, "", 1, bufferqueuelen ) 459 buffer = table_concat( bufferqueue, "", 1, bufferqueuelen )
459 succ, err, byte = send( socket, buffer, 1, bufferlen ) 460 succ, err, byte = send( socket, buffer, 1, bufferlen )
460 count = ( succ or byte or 0 ) * STAT_UNIT 461 count = ( succ or byte or 0 ) * STAT_UNIT
461 sendtraffic = sendtraffic + count 462 sendtraffic = sendtraffic + count
462 _sendtraffic = _sendtraffic + count 463 _sendtraffic = _sendtraffic + count
463 _ = _cleanqueue and clean( bufferqueue ) 464 _ = _cleanqueue and clean( bufferqueue )
464 --out_put( "server.lua: sended '", buffer, "', bytes: ", tostring(succ), ", error: ", tostring(err), ", part: ", tostring(byte), ", to: ", tostring(ip), ":", tostring(clientport) ) 465 --out_put( "server.lua: sended '", buffer, "', bytes: ", tostring(succ), ", error: ", tostring(err), ", part: ", tostring(byte), ", to: ", tostring(ip), ":", tostring(clientport) )
465 else 466 else
466 succ, err, count = false, "closed", 0; 467 succ, err, count = false, "closed", 0;
467 end 468 end
468 if succ then -- sending succesful 469 if succ then -- sending succesful
469 bufferqueuelen = 0 470 bufferqueuelen = 0
470 bufferlen = 0 471 bufferlen = 0
471 _sendlistlen = removesocket( _sendlist, socket, _sendlistlen ) -- delete socket from writelist 472 _sendlistlen = removesocket( _sendlist, socket, _sendlistlen ) -- delete socket from writelist
472 _ = needtls and handler:starttls(nil, true) 473 _ = needtls and handler:starttls(nil, true)
473 _writetimes[ handler ] = nil 474 _writetimes[ handler ] = nil
474 _ = toclose and handler.close( ) 475 _ = toclose and handler.close( )
475 return true 476 return true
476 elseif byte and ( err == "timeout" or err == "wantwrite" ) then -- want write 477 elseif byte and ( err == "timeout" or err == "wantwrite" ) then -- want write
477 buffer = string_sub( buffer, byte + 1, bufferlen ) -- new buffer 478 buffer = string_sub( buffer, byte + 1, bufferlen ) -- new buffer
478 bufferqueue[ 1 ] = buffer -- insert new buffer in queue 479 bufferqueue[ 1 ] = buffer -- insert new buffer in queue
479 bufferqueuelen = 1 480 bufferqueuelen = 1
480 bufferlen = bufferlen - byte 481 bufferlen = bufferlen - byte
481 _writetimes[ handler ] = _currenttime 482 _writetimes[ handler ] = _currenttime
482 return true 483 return true
483 else -- connection was closed during sending or fatal error 484 else -- connection was closed during sending or fatal error
484 out_put( "server.lua: client ", tostring(ip), ":", tostring(clientport), " write error: ", tostring(err) ) 485 out_put( "server.lua: client ", tostring(ip), ":", tostring(clientport), " write error: ", tostring(err) )
485 fatalerror = true 486 fatalerror = true
486 disconnect( handler, err ) 487 disconnect( handler, err )
487 _ = handler and handler.close( ) 488 _ = handler and handler.close( )
488 return false 489 return false
489 end 490 end
490 end 491 end
491 492
492 -- Set the sslctx 493 -- Set the sslctx
493 local handshake; 494 local handshake;
494 function handler.set_sslctx(self, new_sslctx) 495 function handler.set_sslctx(self, new_sslctx)
495 ssl = true 496 ssl = true
496 sslctx = new_sslctx; 497 sslctx = new_sslctx;
497 local wrote 498 local wrote
498 local read 499 local read
499 handshake = coroutine_wrap( function( client ) -- create handshake coroutine 500 handshake = coroutine_wrap( function( client ) -- create handshake coroutine
500 local err 501 local err
501 for i = 1, _maxsslhandshake do 502 for i = 1, _maxsslhandshake do
502 _sendlistlen = ( wrote and removesocket( _sendlist, client, _sendlistlen ) ) or _sendlistlen 503 _sendlistlen = ( wrote and removesocket( _sendlist, client, _sendlistlen ) ) or _sendlistlen
503 _readlistlen = ( read and removesocket( _readlist, client, _readlistlen ) ) or _readlistlen 504 _readlistlen = ( read and removesocket( _readlist, client, _readlistlen ) ) or _readlistlen
504 read, wrote = nil, nil 505 read, wrote = nil, nil
505 _, err = client:dohandshake( ) 506 _, err = client:dohandshake( )
506 if not err then 507 if not err then
507 out_put( "server.lua: ssl handshake done" ) 508 out_put( "server.lua: ssl handshake done" )
508 handler.readbuffer = _readbuffer -- when handshake is done, replace the handshake function with regular functions 509 handler.readbuffer = _readbuffer -- when handshake is done, replace the handshake function with regular functions
509 handler.sendbuffer = _sendbuffer 510 handler.sendbuffer = _sendbuffer
510 _ = status and status( handler, "ssl-handshake-complete" ) 511 _ = status and status( handler, "ssl-handshake-complete" )
511 _readlistlen = addsocket(_readlist, client, _readlistlen) 512 _readlistlen = addsocket(_readlist, client, _readlistlen)
512 return true 513 return true
513 else 514 else
514 out_put( "server.lua: error during ssl handshake: ", tostring(err) ) 515 out_put( "server.lua: error during ssl handshake: ", tostring(err) )
515 if err == "wantwrite" and not wrote then 516 if err == "wantwrite" and not wrote then
516 _sendlistlen = addsocket(_sendlist, client, _sendlistlen) 517 _sendlistlen = addsocket(_sendlist, client, _sendlistlen)
517 wrote = true 518 wrote = true
518 elseif err == "wantread" and not read then 519 elseif err == "wantread" and not read then
519 _readlistlen = addsocket(_readlist, client, _readlistlen) 520 _readlistlen = addsocket(_readlist, client, _readlistlen)
520 read = true 521 read = true
521 else 522 else
522 break; 523 break;
523 end 524 end
524 --coroutine_yield( handler, nil, err ) -- handshake not finished 525 --coroutine_yield( handler, nil, err ) -- handshake not finished
525 coroutine_yield( ) 526 coroutine_yield( )
526 end 527 end
527 end 528 end
528 disconnect( handler, "ssl handshake failed" ) 529 disconnect( handler, "ssl handshake failed" )
529 _ = handler and handler:close( true ) -- forced disconnect 530 _ = handler and handler:close( true ) -- forced disconnect
530 return false -- handshake failed 531 return false -- handshake failed
531 end 532 end
532 ) 533 )
533 end 534 end
534 if sslctx then -- ssl? 535 if sslctx then -- ssl?
535 handler:set_sslctx(sslctx); 536 handler:set_sslctx(sslctx);
536 out_put("server.lua: ", "starting ssl handshake") 537 out_put("server.lua: ", "starting ssl handshake")
537 local err 538 local err
538 socket, err = ssl_wrap( socket, sslctx ) -- wrap socket 539 socket, err = ssl_wrap( socket, sslctx ) -- wrap socket
539 if err then 540 if err then
540 out_put( "server.lua: ssl error: ", tostring(err) ) 541 out_put( "server.lua: ssl error: ", tostring(err) )
541 --mem_free( ) 542 --mem_free( )
542 return nil, nil, err -- fatal error 543 return nil, nil, err -- fatal error
543 end 544 end
544 socket:settimeout( 0 ) 545 socket:settimeout( 0 )
545 handler.readbuffer = handshake 546 handler.readbuffer = handshake
546 handler.sendbuffer = handshake 547 handler.sendbuffer = handshake
547 handshake( socket ) -- do handshake 548 handshake( socket ) -- do handshake
548 if not socket then 549 if not socket then
549 return nil, nil, "ssl handshake failed"; 550 return nil, nil, "ssl handshake failed";
550 end 551 end
551 else 552 else
552 local sslctx; 553 local sslctx;
553 handler.starttls = function( self, _sslctx, now ) 554 handler.starttls = function( self, _sslctx, now )
554 if _sslctx then 555 if _sslctx then
555 sslctx = _sslctx; 556 sslctx = _sslctx;
556 handler:set_sslctx(sslctx); 557 handler:set_sslctx(sslctx);
557 end 558 end
558 if not now then 559 if not now then
559 out_put "server.lua: we need to do tls, but delaying until later" 560 out_put "server.lua: we need to do tls, but delaying until later"
560 needtls = true 561 needtls = true
561 return 562 return
562 end 563 end
563 out_put( "server.lua: attempting to start tls on " .. tostring( socket ) ) 564 out_put( "server.lua: attempting to start tls on " .. tostring( socket ) )
564 local oldsocket, err = socket 565 local oldsocket, err = socket
565 socket, err = ssl_wrap( socket, sslctx ) -- wrap socket 566 socket, err = ssl_wrap( socket, sslctx ) -- wrap socket
566 --out_put( "server.lua: sslwrapped socket is " .. tostring( socket ) ) 567 --out_put( "server.lua: sslwrapped socket is " .. tostring( socket ) )
567 if err then 568 if err then
568 out_put( "server.lua: error while starting tls on client: ", tostring(err) ) 569 out_put( "server.lua: error while starting tls on client: ", tostring(err) )
569 return nil, err -- fatal error 570 return nil, err -- fatal error
570 end 571 end
571 572
572 socket:settimeout( 0 ) 573 socket:settimeout( 0 )
573 574
574 -- add the new socket to our system 575 -- add the new socket to our system
575 576
576 send = socket.send 577 send = socket.send
577 receive = socket.receive 578 receive = socket.receive
578 shutdown = id 579 shutdown = id
579 580
580 _socketlist[ socket ] = handler 581 _socketlist[ socket ] = handler
581 _readlistlen = addsocket(_readlist, socket, _readlistlen) 582 _readlistlen = addsocket(_readlist, socket, _readlistlen)
582 583
583 -- remove traces of the old socket 584 -- remove traces of the old socket
584 585
585 _readlistlen = removesocket( _readlist, oldsocket, _readlistlen ) 586 _readlistlen = removesocket( _readlist, oldsocket, _readlistlen )
586 _sendlistlen = removesocket( _sendlist, oldsocket, _sendlistlen ) 587 _sendlistlen = removesocket( _sendlist, oldsocket, _sendlistlen )
587 _socketlist[ oldsocket ] = nil 588 _socketlist[ oldsocket ] = nil
588 589
589 handler.starttls = nil 590 handler.starttls = nil
590 needtls = nil 591 needtls = nil
591 592
592 -- Secure now 593 -- Secure now
593 ssl = true 594 ssl = true
594 595
595 handler.readbuffer = handshake 596 handler.readbuffer = handshake
596 handler.sendbuffer = handshake 597 handler.sendbuffer = handshake
597 handshake( socket ) -- do handshake 598 handshake( socket ) -- do handshake
598 end 599 end
599 handler.readbuffer = _readbuffer 600 handler.readbuffer = _readbuffer
600 handler.sendbuffer = _sendbuffer 601 handler.sendbuffer = _sendbuffer
601 end 602 end
602 603
603 send = socket.send 604 send = socket.send
604 receive = socket.receive 605 receive = socket.receive
605 shutdown = ( ssl and id ) or socket.shutdown 606 shutdown = ( ssl and id ) or socket.shutdown
606 607
607 _socketlist[ socket ] = handler 608 _socketlist[ socket ] = handler
608 _readlistlen = addsocket(_readlist, socket, _readlistlen) 609 _readlistlen = addsocket(_readlist, socket, _readlistlen)
609 610
610 return handler, socket 611 return handler, socket
611 end 612 end
612 613
613 id = function( ) 614 id = function( )
614 end 615 end
615 616
616 idfalse = function( ) 617 idfalse = function( )
617 return false 618 return false
618 end 619 end
619 620
620 addsocket = function( list, socket, len ) 621 addsocket = function( list, socket, len )
621 if not list[ socket ] then 622 if not list[ socket ] then
622 len = len + 1 623 len = len + 1
623 list[ len ] = socket 624 list[ len ] = socket
624 list[ socket ] = len 625 list[ socket ] = len
625 end 626 end
626 return len; 627 return len;
627 end 628 end
628 629
629 removesocket = function( list, socket, len ) -- this function removes sockets from a list ( copied from copas ) 630 removesocket = function( list, socket, len ) -- this function removes sockets from a list ( copied from copas )
630 local pos = list[ socket ] 631 local pos = list[ socket ]
631 if pos then 632 if pos then
632 list[ socket ] = nil 633 list[ socket ] = nil
633 local last = list[ len ] 634 local last = list[ len ]
634 list[ len ] = nil 635 list[ len ] = nil
635 if last ~= socket then 636 if last ~= socket then
636 list[ last ] = pos 637 list[ last ] = pos
637 list[ pos ] = last 638 list[ pos ] = last
638 end 639 end
639 return len - 1 640 return len - 1
640 end 641 end
641 return len 642 return len
642 end 643 end
643 644
644 closesocket = function( socket ) 645 closesocket = function( socket )
645 _sendlistlen = removesocket( _sendlist, socket, _sendlistlen ) 646 _sendlistlen = removesocket( _sendlist, socket, _sendlistlen )
646 _readlistlen = removesocket( _readlist, socket, _readlistlen ) 647 _readlistlen = removesocket( _readlist, socket, _readlistlen )
647 _socketlist[ socket ] = nil 648 _socketlist[ socket ] = nil
648 socket:close( ) 649 socket:close( )
649 --mem_free( ) 650 --mem_free( )
650 end 651 end
651 652
652 ----------------------------------// PUBLIC //-- 653 ----------------------------------// PUBLIC //--
653 654
654 addserver = function( addr, port, listeners, pattern, sslctx ) -- this function provides a way for other scripts to reg a server 655 addserver = function( addr, port, listeners, pattern, sslctx ) -- this function provides a way for other scripts to reg a server
655 local err 656 local err
656 if type( listeners ) ~= "table" then 657 if type( listeners ) ~= "table" then
657 err = "invalid listener table" 658 err = "invalid listener table"
658 end 659 end
659 if not type( port ) == "number" or not ( port >= 0 and port <= 65535 ) then 660 if not type( port ) == "number" or not ( port >= 0 and port <= 65535 ) then
660 err = "invalid port" 661 err = "invalid port"
661 elseif _server[ port ] then 662 elseif _server[ port ] then
662 err = "listeners on port '" .. port .. "' already exist" 663 err = "listeners on port '" .. port .. "' already exist"
663 elseif sslctx and not luasec then 664 elseif sslctx and not luasec then
664 err = "luasec not found" 665 err = "luasec not found"
665 end 666 end
666 if err then 667 if err then
667 out_error( "server.lua, port ", port, ": ", err ) 668 out_error( "server.lua, port ", port, ": ", err )
668 return nil, err 669 return nil, err
669 end 670 end
670 addr = addr or "*" 671 addr = addr or "*"
671 local server, err = socket_bind( addr, port ) 672 local server, err = socket_bind( addr, port )
672 if err then 673 if err then
673 out_error( "server.lua, port ", port, ": ", err ) 674 out_error( "server.lua, port ", port, ": ", err )
674 return nil, err 675 return nil, err
675 end 676 end
676 local handler, err = wrapserver( listeners, server, addr, port, pattern, sslctx, _maxclientsperserver ) -- wrap new server socket 677 local handler, err = wrapserver( listeners, server, addr, port, pattern, sslctx, _maxclientsperserver ) -- wrap new server socket
677 if not handler then 678 if not handler then
678 server:close( ) 679 server:close( )
679 return nil, err 680 return nil, err
680 end 681 end
681 server:settimeout( 0 ) 682 server:settimeout( 0 )
682 _readlistlen = addsocket(_readlist, server, _readlistlen) 683 _readlistlen = addsocket(_readlist, server, _readlistlen)
683 _server[ port ] = handler 684 _server[ port ] = handler
684 _socketlist[ server ] = handler 685 _socketlist[ server ] = handler
685 out_put( "server.lua: new "..(sslctx and "ssl " or "").."server listener on '", addr, ":", port, "'" ) 686 out_put( "server.lua: new "..(sslctx and "ssl " or "").."server listener on '", addr, ":", port, "'" )
686 return handler 687 return handler
687 end 688 end
688 689
689 getserver = function ( port ) 690 getserver = function ( port )
690 return _server[ port ]; 691 return _server[ port ];
691 end 692 end
692 693
693 removeserver = function( port ) 694 removeserver = function( port )
694 local handler = _server[ port ] 695 local handler = _server[ port ]
695 if not handler then 696 if not handler then
696 return nil, "no server found on port '" .. tostring( port ) .. "'" 697 return nil, "no server found on port '" .. tostring( port ) .. "'"
697 end 698 end
698 handler:close( ) 699 handler:close( )
699 _server[ port ] = nil 700 _server[ port ] = nil
700 return true 701 return true
701 end 702 end
702 703
703 closeall = function( ) 704 closeall = function( )
704 for _, handler in pairs( _socketlist ) do 705 for _, handler in pairs( _socketlist ) do
705 handler:close( ) 706 handler:close( )
706 _socketlist[ _ ] = nil 707 _socketlist[ _ ] = nil
707 end 708 end
708 _readlistlen = 0 709 _readlistlen = 0
709 _sendlistlen = 0 710 _sendlistlen = 0
710 _timerlistlen = 0 711 _timerlistlen = 0
711 _server = { } 712 _server = { }
712 _readlist = { } 713 _readlist = { }
713 _sendlist = { } 714 _sendlist = { }
714 _timerlist = { } 715 _timerlist = { }
715 _socketlist = { } 716 _socketlist = { }
716 --mem_free( ) 717 --mem_free( )
717 end 718 end
718 719
719 getsettings = function( ) 720 getsettings = function( )
720 return _selecttimeout, _sleeptime, _maxsendlen, _maxreadlen, _checkinterval, _sendtimeout, _readtimeout, _cleanqueue, _maxclientsperserver, _maxsslhandshake 721 return _selecttimeout, _sleeptime, _maxsendlen, _maxreadlen, _checkinterval, _sendtimeout, _readtimeout, _cleanqueue, _maxclientsperserver, _maxsslhandshake
721 end 722 end
722 723
723 changesettings = function( new ) 724 changesettings = function( new )
724 if type( new ) ~= "table" then 725 if type( new ) ~= "table" then
725 return nil, "invalid settings table" 726 return nil, "invalid settings table"
726 end 727 end
727 _selecttimeout = tonumber( new.timeout ) or _selecttimeout 728 _selecttimeout = tonumber( new.timeout ) or _selecttimeout
728 _sleeptime = tonumber( new.sleeptime ) or _sleeptime 729 _sleeptime = tonumber( new.sleeptime ) or _sleeptime
729 _maxsendlen = tonumber( new.maxsendlen ) or _maxsendlen 730 _maxsendlen = tonumber( new.maxsendlen ) or _maxsendlen
730 _maxreadlen = tonumber( new.maxreadlen ) or _maxreadlen 731 _maxreadlen = tonumber( new.maxreadlen ) or _maxreadlen
731 _checkinterval = tonumber( new.checkinterval ) or _checkinterval 732 _checkinterval = tonumber( new.checkinterval ) or _checkinterval
732 _sendtimeout = tonumber( new.sendtimeout ) or _sendtimeout 733 _sendtimeout = tonumber( new.sendtimeout ) or _sendtimeout
733 _readtimeout = tonumber( new.readtimeout ) or _readtimeout 734 _readtimeout = tonumber( new.readtimeout ) or _readtimeout
734 _cleanqueue = new.cleanqueue 735 _cleanqueue = new.cleanqueue
735 _maxclientsperserver = new._maxclientsperserver or _maxclientsperserver 736 _maxclientsperserver = new._maxclientsperserver or _maxclientsperserver
736 _maxsslhandshake = new._maxsslhandshake or _maxsslhandshake 737 _maxsslhandshake = new._maxsslhandshake or _maxsslhandshake
737 return true 738 return true
738 end 739 end
739 740
740 addtimer = function( listener ) 741 addtimer = function( listener )
741 if type( listener ) ~= "function" then 742 if type( listener ) ~= "function" then
742 return nil, "invalid listener function" 743 return nil, "invalid listener function"
743 end 744 end
744 _timerlistlen = _timerlistlen + 1 745 _timerlistlen = _timerlistlen + 1
745 _timerlist[ _timerlistlen ] = listener 746 _timerlist[ _timerlistlen ] = listener
746 return true 747 return true
747 end 748 end
748 749
749 stats = function( ) 750 stats = function( )
750 return _readtraffic, _sendtraffic, _readlistlen, _sendlistlen, _timerlistlen 751 return _readtraffic, _sendtraffic, _readlistlen, _sendlistlen, _timerlistlen
751 end 752 end
752 753
753 local dontstop = true; -- thinking about tomorrow, ... 754 local dontstop = true; -- thinking about tomorrow, ...
754 755
755 setquitting = function (quit) 756 setquitting = function (quit)
756 dontstop = not quit; 757 dontstop = not quit;
757 return; 758 return;
758 end 759 end
759 760
760 loop = function( ) -- this is the main loop of the program 761 loop = function( ) -- this is the main loop of the program
761 while dontstop do 762 while dontstop do
762 local read, write, err = socket_select( _readlist, _sendlist, _selecttimeout ) 763 local read, write, err = socket_select( _readlist, _sendlist, _selecttimeout )
763 for i, socket in ipairs( write ) do -- send data waiting in writequeues 764 for i, socket in ipairs( write ) do -- send data waiting in writequeues
764 local handler = _socketlist[ socket ] 765 local handler = _socketlist[ socket ]
765 if handler then 766 if handler then
766 handler.sendbuffer( ) 767 handler.sendbuffer( )
767 else 768 else
768 closesocket( socket ) 769 closesocket( socket )
769 out_put "server.lua: found no handler and closed socket (writelist)" -- this should not happen 770 out_put "server.lua: found no handler and closed socket (writelist)" -- this should not happen
770 end 771 end
771 end 772 end
772 for i, socket in ipairs( read ) do -- receive data 773 for i, socket in ipairs( read ) do -- receive data
773 local handler = _socketlist[ socket ] 774 local handler = _socketlist[ socket ]
774 if handler then 775 if handler then
775 handler.readbuffer( ) 776 handler.readbuffer( )
776 else 777 else
777 closesocket( socket ) 778 closesocket( socket )
778 out_put "server.lua: found no handler and closed socket (readlist)" -- this can happen 779 out_put "server.lua: found no handler and closed socket (readlist)" -- this can happen
779 end 780 end
780 end 781 end
781 for handler, err in pairs( _closelist ) do 782 for handler, err in pairs( _closelist ) do
782 handler.disconnect( )( handler, err ) 783 handler.disconnect( )( handler, err )
783 handler:close( true ) -- forced disconnect 784 handler:close( true ) -- forced disconnect
784 end 785 end
785 clean( _closelist ) 786 clean( _closelist )
786 _currenttime = os_time( ) 787 _currenttime = os_time( )
787 if os_difftime( _currenttime - _timer ) >= 1 then 788 if os_difftime( _currenttime - _timer ) >= 1 then
788 for i = 1, _timerlistlen do 789 for i = 1, _timerlistlen do
789 _timerlist[ i ]( _currenttime ) -- fire timers 790 _timerlist[ i ]( _currenttime ) -- fire timers
790 end 791 end
791 _timer = _currenttime 792 _timer = _currenttime
792 end 793 end
793 socket_sleep( _sleeptime ) -- wait some time 794 socket_sleep( _sleeptime ) -- wait some time
794 --collectgarbage( ) 795 --collectgarbage( )
795 end 796 end
796 return "quitting" 797 return "quitting"
797 end 798 end
798 799
799 local function get_backend() 800 local function get_backend()
800 return "select"; 801 return "select";
801 end 802 end
802 803
803 --// EXPERIMENTAL //-- 804 --// EXPERIMENTAL //--
804 805
805 local wrapclient = function( socket, ip, serverport, listeners, pattern, sslctx ) 806 local wrapclient = function( socket, ip, serverport, listeners, pattern, sslctx )
806 local handler = wrapconnection( nil, listeners, socket, ip, serverport, "clientport", pattern, sslctx ) 807 local handler = wrapconnection( nil, listeners, socket, ip, serverport, "clientport", pattern, sslctx )
807 _socketlist[ socket ] = handler 808 _socketlist[ socket ] = handler
808 _sendlistlen = addsocket(_sendlist, socket, _sendlistlen) 809 _sendlistlen = addsocket(_sendlist, socket, _sendlistlen)
809 return handler, socket 810 return handler, socket
810 end 811 end
811 812
812 local addclient = function( address, port, listeners, pattern, sslctx ) 813 local addclient = function( address, port, listeners, pattern, sslctx )
813 local client, err = luasocket.tcp( ) 814 local client, err = luasocket.tcp( )
814 if err then 815 if err then
815 return nil, err 816 return nil, err
816 end 817 end
817 client:settimeout( 0 ) 818 client:settimeout( 0 )
818 _, err = client:connect( address, port ) 819 _, err = client:connect( address, port )
819 if err then -- try again 820 if err then -- try again
820 local handler = wrapclient( client, address, port, listeners ) 821 local handler = wrapclient( client, address, port, listeners )
821 else 822 else
822 wrapconnection( nil, listeners, client, address, port, "clientport", pattern, sslctx ) 823 wrapconnection( nil, listeners, client, address, port, "clientport", pattern, sslctx )
823 end 824 end
824 end 825 end
825 826
826 --// EXPERIMENTAL //-- 827 --// EXPERIMENTAL //--
827 828
828 ----------------------------------// BEGIN //-- 829 ----------------------------------// BEGIN //--
833 834
834 _timer = os_time( ) 835 _timer = os_time( )
835 _starttime = os_time( ) 836 _starttime = os_time( )
836 837
837 addtimer( function( ) 838 addtimer( function( )
838 local difftime = os_difftime( _currenttime - _starttime ) 839 local difftime = os_difftime( _currenttime - _starttime )
839 if difftime > _checkinterval then 840 if difftime > _checkinterval then
840 _starttime = _currenttime 841 _starttime = _currenttime
841 for handler, timestamp in pairs( _writetimes ) do 842 for handler, timestamp in pairs( _writetimes ) do
842 if os_difftime( _currenttime - timestamp ) > _sendtimeout then 843 if os_difftime( _currenttime - timestamp ) > _sendtimeout then
843 --_writetimes[ handler ] = nil 844 --_writetimes[ handler ] = nil
844 handler.disconnect( )( handler, "send timeout" ) 845 handler.disconnect( )( handler, "send timeout" )
845 handler:close( true ) -- forced disconnect 846 handler:close( true ) -- forced disconnect
846 end 847 end
847 end 848 end
848 for handler, timestamp in pairs( _readtimes ) do 849 for handler, timestamp in pairs( _readtimes ) do
849 if os_difftime( _currenttime - timestamp ) > _readtimeout then 850 if os_difftime( _currenttime - timestamp ) > _readtimeout then
850 --_readtimes[ handler ] = nil 851 --_readtimes[ handler ] = nil
851 handler.disconnect( )( handler, "read timeout" ) 852 handler.disconnect( )( handler, "read timeout" )
852 handler:close( ) -- forced disconnect? 853 handler:close( ) -- forced disconnect?
853 end 854 end
854 end 855 end
855 end 856 end
856 end 857 end
857 ) 858 )
858 859
859 local function setlogger(new_logger) 860 local function setlogger(new_logger)
860 local old_logger = log; 861 local old_logger = log;
861 if new_logger then 862 if new_logger then
866 867
867 ----------------------------------// PUBLIC INTERFACE //-- 868 ----------------------------------// PUBLIC INTERFACE //--
868 869
869 return { 870 return {
870 871
871 addclient = addclient, 872 addclient = addclient,
872 wrapclient = wrapclient, 873 wrapclient = wrapclient,
873 874
874 loop = loop, 875 loop = loop,
875 stats = stats, 876 stats = stats,
876 closeall = closeall, 877 closeall = closeall,
877 addtimer = addtimer, 878 addtimer = addtimer,
878 addserver = addserver, 879 addserver = addserver,
879 getserver = getserver, 880 getserver = getserver,
880 setlogger = setlogger, 881 setlogger = setlogger,
881 getsettings = getsettings, 882 getsettings = getsettings,
882 setquitting = setquitting, 883 setquitting = setquitting,
883 removeserver = removeserver, 884 removeserver = removeserver,
884 get_backend = get_backend, 885 get_backend = get_backend,
885 changesettings = changesettings, 886 changesettings = changesettings,
886 } 887 }