Comparison

net/server.lua @ 64:bcd0a3975580

Convert spaces->tabs
author Matthew Wild <mwild1@gmail.com>
date Sun, 05 Oct 2008 02:48:39 +0100
parent 12:90f22275f7ae
child 65:9c471840acb9
comparison
equal deleted inserted replaced
63:4c27740fdeff 64:bcd0a3975580
1 --[[ 1 --[[
2 2
3 server.lua by blastbeat of the luadch project 3 server.lua by blastbeat of the luadch project
4 4
5 re-used here under the MIT/X Consortium License 5 re-used here under the MIT/X Consortium License
6 6
7 - this script contains the server loop of the program 7 - this script contains the server loop of the program
8 - other scripts can reg a server here 8 - other scripts can reg a server here
9 9
10 ]]-- 10 ]]--
11 11
12 ----------------------------------// DECLARATION //-- 12 ----------------------------------// DECLARATION //--
13 13
91 writelist = { } -- arrary with sockets to write to 91 writelist = { } -- arrary with sockets to write to
92 socketlist = { } -- key = socket, value = wrapped socket 92 socketlist = { } -- key = socket, value = wrapped socket
93 timelistener = { } 93 timelistener = { }
94 94
95 stats = function( ) 95 stats = function( )
96 return receivestat, sendstat 96 return receivestat, sendstat
97 end 97 end
98 98
99 wrapserver = function( listener, socket, ip, serverport, mode, sslctx ) -- this function wraps a server 99 wrapserver = function( listener, socket, ip, serverport, mode, sslctx ) -- this function wraps a server
100 100
101 local dispatch, disconnect = listener.listener, listener.disconnect -- dangerous 101 local dispatch, disconnect = listener.listener, listener.disconnect -- dangerous
102 102
103 local wrapclient, err 103 local wrapclient, err
104 104
105 if sslctx then 105 if sslctx then
106 if not ssl_newcontext then 106 if not ssl_newcontext then
107 return nil, "luasec not found" 107 return nil, "luasec not found"
108 -- elseif not cfg_get "use_ssl" then 108 -- elseif not cfg_get "use_ssl" then
109 -- return nil, "ssl is deactivated" 109 -- return nil, "ssl is deactivated"
110 end 110 end
111 if type( sslctx ) ~= "table" then 111 if type( sslctx ) ~= "table" then
112 out_error "server.lua: wrong server sslctx" 112 out_error "server.lua: wrong server sslctx"
113 return nil, "wrong server sslctx" 113 return nil, "wrong server sslctx"
114 end 114 end
115 sslctx, err = ssl_newcontext( sslctx ) 115 sslctx, err = ssl_newcontext( sslctx )
116 if not sslctx then 116 if not sslctx then
117 err = err or "wrong sslctx parameters" 117 err = err or "wrong sslctx parameters"
118 out_error( "server.lua: ", err ) 118 out_error( "server.lua: ", err )
119 return nil, err 119 return nil, err
120 end 120 end
121 wrapclient = wrapsslclient 121 wrapclient = wrapsslclient
122 else 122 else
123 wrapclient = wraptcpclient 123 wrapclient = wraptcpclient
124 end 124 end
125 125
126 local accept = socket.accept 126 local accept = socket.accept
127 local close = socket.close 127 local close = socket.close
128 128
129 --// public methods of the object //-- 129 --// public methods of the object //--
130 130
131 local handler = { } 131 local handler = { }
132 132
133 handler.shutdown = function( ) end 133 handler.shutdown = function( ) end
134 134
135 --[[handler.listener = function( data, err ) 135 --[[handler.listener = function( data, err )
136 return ondata( handler, data, err ) 136 return ondata( handler, data, err )
137 end]] 137 end]]
138 handler.ssl = function( ) 138 handler.ssl = function( )
139 return sslctx and true or false 139 return sslctx and true or false
140 end 140 end
141 handler.close = function( closed ) 141 handler.close = function( closed )
142 _ = not closed and close( socket ) 142 _ = not closed and close( socket )
143 writelen = removesocket( writelist, socket, writelen ) 143 writelen = removesocket( writelist, socket, writelen )
144 readlen = removesocket( readlist, socket, readlen ) 144 readlen = removesocket( readlist, socket, readlen )
145 socketlist[ socket ] = nil 145 socketlist[ socket ] = nil
146 handler = nil 146 handler = nil
147 end 147 end
148 handler.ip = function( ) 148 handler.ip = function( )
149 return ip 149 return ip
150 end 150 end
151 handler.serverport = function( ) 151 handler.serverport = function( )
152 return serverport 152 return serverport
153 end 153 end
154 handler.socket = function( ) 154 handler.socket = function( )
155 return socket 155 return socket
156 end 156 end
157 handler.receivedata = function( ) 157 handler.receivedata = function( )
158 local client, err = accept( socket ) -- try to accept 158 local client, err = accept( socket ) -- try to accept
159 if client then 159 if client then
160 local ip, clientport = client:getpeername( ) 160 local ip, clientport = client:getpeername( )
161 client:settimeout( 0 ) 161 client:settimeout( 0 )
162 local handler, client, err = wrapclient( listener, client, ip, serverport, clientport, mode, sslctx ) -- wrap new client socket 162 local handler, client, err = wrapclient( listener, client, ip, serverport, clientport, mode, sslctx ) -- wrap new client socket
163 if err then -- error while wrapping ssl socket 163 if err then -- error while wrapping ssl socket
164 return false 164 return false
165 end 165 end
166 out_put( "server.lua: accepted new client connection from ", ip, ":", clientport ) 166 out_put( "server.lua: accepted new client connection from ", ip, ":", clientport )
167 return dispatch( handler ) 167 return dispatch( handler )
168 elseif err then -- maybe timeout or something else 168 elseif err then -- maybe timeout or something else
169 out_put( "server.lua: error with new client connection: ", err ) 169 out_put( "server.lua: error with new client connection: ", err )
170 return false 170 return false
171 end 171 end
172 end 172 end
173 return handler 173 return handler
174 end 174 end
175 175
176 wrapsslclient = function( listener, socket, ip, serverport, clientport, mode, sslctx ) -- this function wraps a ssl cleint 176 wrapsslclient = function( listener, socket, ip, serverport, clientport, mode, sslctx ) -- this function wraps a ssl cleint
177 177
178 local dispatch, disconnect = listener.listener, listener.disconnect 178 local dispatch, disconnect = listener.listener, listener.disconnect
179 179
180 --// transform socket to ssl object //-- 180 --// transform socket to ssl object //--
181 181
182 local err 182 local err
183 socket, err = ssl_wrap( socket, sslctx ) -- wrap socket 183 socket, err = ssl_wrap( socket, sslctx ) -- wrap socket
184 if err then 184 if err then
185 out_put( "server.lua: ssl error: ", err ) 185 out_put( "server.lua: ssl error: ", err )
186 return nil, nil, err -- fatal error 186 return nil, nil, err -- fatal error
187 end 187 end
188 socket:settimeout( 0 ) 188 socket:settimeout( 0 )
189 189
190 --// private closures of the object //-- 190 --// private closures of the object //--
191 191
192 local writequeue = { } -- buffer for messages to send 192 local writequeue = { } -- buffer for messages to send
193 193
194 local eol -- end of buffer 194 local eol -- end of buffer
195 195
196 local sstat, rstat = 0, 0 196 local sstat, rstat = 0, 0
197 197
198 --// local import of socket methods //-- 198 --// local import of socket methods //--
199 199
200 local send = socket.send 200 local send = socket.send
201 local receive = socket.receive 201 local receive = socket.receive
202 local close = socket.close 202 local close = socket.close
203 --local shutdown = socket.shutdown 203 --local shutdown = socket.shutdown
204 204
205 --// public methods of the object //-- 205 --// public methods of the object //--
206 206
207 local handler = { } 207 local handler = { }
208 208
209 handler.getstats = function( ) 209 handler.getstats = function( )
210 return rstat, sstat 210 return rstat, sstat
211 end 211 end
212 212
213 handler.listener = function( data, err ) 213 handler.listener = function( data, err )
214 return listener( handler, data, err ) 214 return listener( handler, data, err )
215 end 215 end
216 handler.ssl = function( ) 216 handler.ssl = function( )
217 return true 217 return true
218 end 218 end
219 handler.send = function( _, data, i, j ) 219 handler.send = function( _, data, i, j )
220 return send( socket, data, i, j ) 220 return send( socket, data, i, j )
221 end 221 end
222 handler.receive = function( pattern, prefix ) 222 handler.receive = function( pattern, prefix )
223 return receive( socket, pattern, prefix ) 223 return receive( socket, pattern, prefix )
224 end 224 end
225 handler.shutdown = function( pattern ) 225 handler.shutdown = function( pattern )
226 --return shutdown( socket, pattern ) 226 --return shutdown( socket, pattern )
227 end 227 end
228 handler.close = function( closed ) 228 handler.close = function( closed )
229 close( socket ) 229 close( socket )
230 writelen = ( eol and removesocket( writelist, socket, writelen ) ) or writelen 230 writelen = ( eol and removesocket( writelist, socket, writelen ) ) or writelen
231 readlen = removesocket( readlist, socket, readlen ) 231 readlen = removesocket( readlist, socket, readlen )
232 socketlist[ socket ] = nil 232 socketlist[ socket ] = nil
233 out_put "server.lua: closed handler and removed socket from list" 233 out_put "server.lua: closed handler and removed socket from list"
234 end 234 end
235 handler.ip = function( ) 235 handler.ip = function( )
236 return ip 236 return ip
237 end 237 end
238 handler.serverport = function( ) 238 handler.serverport = function( )
239 return serverport 239 return serverport
240 end 240 end
241 handler.clientport = function( ) 241 handler.clientport = function( )
242 return clientport 242 return clientport
243 end 243 end
244 244
245 handler.write = function( data ) 245 handler.write = function( data )
246 if not eol then 246 if not eol then
247 writelen = writelen + 1 247 writelen = writelen + 1
248 writelist[ writelen ] = socket 248 writelist[ writelen ] = socket
249 eol = 0 249 eol = 0
250 end 250 end
251 eol = eol + 1 251 eol = eol + 1
252 writequeue[ eol ] = data 252 writequeue[ eol ] = data
253 end 253 end
254 handler.writequeue = function( ) 254 handler.writequeue = function( )
255 return writequeue 255 return writequeue
256 end 256 end
257 handler.socket = function( ) 257 handler.socket = function( )
258 return socket 258 return socket
259 end 259 end
260 handler.mode = function( ) 260 handler.mode = function( )
261 return mode 261 return mode
262 end 262 end
263 handler._receivedata = function( ) 263 handler._receivedata = function( )
264 local data, err, part = receive( socket, mode ) -- receive data in "mode" 264 local data, err, part = receive( socket, mode ) -- receive data in "mode"
265 if not err or ( err == "timeout" or err == "wantread" ) then -- received something 265 if not err or ( err == "timeout" or err == "wantread" ) then -- received something
266 local data = data or part or "" 266 local data = data or part or ""
267 local count = #data * STAT_UNIT 267 local count = #data * STAT_UNIT
268 rstat = rstat + count 268 rstat = rstat + count
269 receivestat = receivestat + count 269 receivestat = receivestat + count
270 out_put( "server.lua: read data '", data, "', error: ", err ) 270 out_put( "server.lua: read data '", data, "', error: ", err )
271 return dispatch( handler, data, err ) 271 return dispatch( handler, data, err )
272 else -- connections was closed or fatal error 272 else -- connections was closed or fatal error
273 out_put( "server.lua: client ", ip, ":", clientport, " error: ", err ) 273 out_put( "server.lua: client ", ip, ":", clientport, " error: ", err )
274 handler.close( ) 274 handler.close( )
275 disconnect( handler, err ) 275 disconnect( handler, err )
276 writequeue = nil 276 writequeue = nil
277 handler = nil 277 handler = nil
278 return false 278 return false
279 end 279 end
280 end 280 end
281 handler._dispatchdata = function( ) -- this function writes data to handlers 281 handler._dispatchdata = function( ) -- this function writes data to handlers
282 local buffer = table_concat( writequeue, "", 1, eol ) 282 local buffer = table_concat( writequeue, "", 1, eol )
283 local succ, err, byte = send( socket, buffer ) 283 local succ, err, byte = send( socket, buffer )
284 local count = ( succ or 0 ) * STAT_UNIT 284 local count = ( succ or 0 ) * STAT_UNIT
285 sstat = sstat + count 285 sstat = sstat + count
286 sendstat = sendstat + count 286 sendstat = sendstat + count
287 out_put( "server.lua: sended '", buffer, "', bytes: ", succ, ", error: ", err, ", part: ", byte, ", to: ", ip, ":", clientport ) 287 out_put( "server.lua: sended '", buffer, "', bytes: ", succ, ", error: ", err, ", part: ", byte, ", to: ", ip, ":", clientport )
288 if succ then -- sending succesful 288 if succ then -- sending succesful
289 --writequeue = { } 289 --writequeue = { }
290 eol = nil 290 eol = nil
291 writelen = removesocket( writelist, socket, writelen ) -- delete socket from writelist 291 writelen = removesocket( writelist, socket, writelen ) -- delete socket from writelist
292 return true 292 return true
293 elseif byte and ( err == "timeout" or err == "wantwrite" ) then -- want write 293 elseif byte and ( err == "timeout" or err == "wantwrite" ) then -- want write
294 buffer = string_sub( buffer, byte + 1, -1 ) -- new buffer 294 buffer = string_sub( buffer, byte + 1, -1 ) -- new buffer
295 writequeue[ 1 ] = buffer -- insert new buffer in queue 295 writequeue[ 1 ] = buffer -- insert new buffer in queue
296 eol = 1 296 eol = 1
297 return true 297 return true
298 else -- connection was closed during sending or fatal error 298 else -- connection was closed during sending or fatal error
299 out_put( "server.lua: client ", ip, ":", clientport, " error: ", err ) 299 out_put( "server.lua: client ", ip, ":", clientport, " error: ", err )
300 handler.close( ) 300 handler.close( )
301 disconnect( handler, err ) 301 disconnect( handler, err )
302 writequeue = nil 302 writequeue = nil
303 handler = nil 303 handler = nil
304 return false 304 return false
305 end 305 end
306 end 306 end
307 307
308 -- // COMPAT // -- 308 -- // COMPAT // --
309 309
310 handler.getIp = handler.ip 310 handler.getIp = handler.ip
311 handler.getPort = handler.clientport 311 handler.getPort = handler.clientport
312 312
313 --// handshake //-- 313 --// handshake //--
314 314
315 local wrote 315 local wrote
316 316
317 handler.handshake = coroutine_wrap( function( client ) 317 handler.handshake = coroutine_wrap( function( client )
318 local err 318 local err
319 for i = 1, 10 do -- 10 handshake attemps 319 for i = 1, 10 do -- 10 handshake attemps
320 _, err = client:dohandshake( ) 320 _, err = client:dohandshake( )
321 if not err then 321 if not err then
322 out_put( "server.lua: ssl handshake done" ) 322 out_put( "server.lua: ssl handshake done" )
323 writelen = ( wrote and removesocket( writelist, socket, writelen ) ) or writelen 323 writelen = ( wrote and removesocket( writelist, socket, writelen ) ) or writelen
324 handler.receivedata = handler._receivedata -- when handshake is done, replace the handshake function with regular functions 324 handler.receivedata = handler._receivedata -- when handshake is done, replace the handshake function with regular functions
325 handler.dispatchdata = handler._dispatchdata 325 handler.dispatchdata = handler._dispatchdata
326 return dispatch( handler ) 326 return dispatch( handler )
327 else 327 else
328 out_put( "server.lua: error during ssl handshake: ", err ) 328 out_put( "server.lua: error during ssl handshake: ", err )
329 if err == "wantwrite" then 329 if err == "wantwrite" then
330 if wrote == nil then 330 if wrote == nil then
331 writelen = writelen + 1 331 writelen = writelen + 1
332 writelist[ writelen ] = client 332 writelist[ writelen ] = client
333 wrote = true 333 wrote = true
334 end 334 end
335 end 335 end
336 coroutine_yield( handler, nil, err ) -- handshake not finished 336 coroutine_yield( handler, nil, err ) -- handshake not finished
337 end 337 end
338 end 338 end
339 _ = err ~= "closed" and close( socket ) 339 _ = err ~= "closed" and close( socket )
340 handler.close( ) 340 handler.close( )
341 disconnect( handler, err ) 341 disconnect( handler, err )
342 writequeue = nil 342 writequeue = nil
343 handler = nil 343 handler = nil
344 return false -- handshake failed 344 return false -- handshake failed
345 end 345 end
346 ) 346 )
347 handler.receivedata = handler.handshake 347 handler.receivedata = handler.handshake
348 handler.dispatchdata = handler.handshake 348 handler.dispatchdata = handler.handshake
349 349
350 handler.handshake( socket ) -- do handshake 350 handler.handshake( socket ) -- do handshake
351 351
352 socketlist[ socket ] = handler 352 socketlist[ socket ] = handler
353 readlen = readlen + 1 353 readlen = readlen + 1
354 readlist[ readlen ] = socket 354 readlist[ readlen ] = socket
355 355
356 return handler, socket 356 return handler, socket
357 end 357 end
358 358
359 wraptcpclient = function( listener, socket, ip, serverport, clientport, mode ) -- this function wraps a socket 359 wraptcpclient = function( listener, socket, ip, serverport, clientport, mode ) -- this function wraps a socket
360 360
361 local dispatch, disconnect = listener.listener, listener.disconnect 361 local dispatch, disconnect = listener.listener, listener.disconnect
362 362
363 --// private closures of the object //-- 363 --// private closures of the object //--
364 364
365 local writequeue = { } -- list for messages to send 365 local writequeue = { } -- list for messages to send
366 366
367 local eol 367 local eol
368 368
369 local rstat, sstat = 0, 0 369 local rstat, sstat = 0, 0
370 370
371 --// local import of socket methods //-- 371 --// local import of socket methods //--
372 372
373 local send = socket.send 373 local send = socket.send
374 local receive = socket.receive 374 local receive = socket.receive
375 local close = socket.close 375 local close = socket.close
376 local shutdown = socket.shutdown 376 local shutdown = socket.shutdown
377 377
378 --// public methods of the object //-- 378 --// public methods of the object //--
379 379
380 local handler = { } 380 local handler = { }
381 381
382 handler.getstats = function( ) 382 handler.getstats = function( )
383 return rstat, sstat 383 return rstat, sstat
384 end 384 end
385 385
386 handler.listener = function( data, err ) 386 handler.listener = function( data, err )
387 return listener( handler, data, err ) 387 return listener( handler, data, err )
388 end 388 end
389 handler.ssl = function( ) 389 handler.ssl = function( )
390 return false 390 return false
391 end 391 end
392 handler.send = function( _, data, i, j ) 392 handler.send = function( _, data, i, j )
393 return send( socket, data, i, j ) 393 return send( socket, data, i, j )
394 end 394 end
395 handler.receive = function( pattern, prefix ) 395 handler.receive = function( pattern, prefix )
396 return receive( socket, pattern, prefix ) 396 return receive( socket, pattern, prefix )
397 end 397 end
398 handler.shutdown = function( pattern ) 398 handler.shutdown = function( pattern )
399 return shutdown( socket, pattern ) 399 return shutdown( socket, pattern )
400 end 400 end
401 handler.close = function( closed ) 401 handler.close = function( closed )
402 _ = not closed and shutdown( socket ) 402 _ = not closed and shutdown( socket )
403 _ = not closed and close( socket ) 403 _ = not closed and close( socket )
404 writelen = ( eol and removesocket( writelist, socket, writelen ) ) or writelen 404 writelen = ( eol and removesocket( writelist, socket, writelen ) ) or writelen
405 readlen = removesocket( readlist, socket, readlen ) 405 readlen = removesocket( readlist, socket, readlen )
406 socketlist[ socket ] = nil 406 socketlist[ socket ] = nil
407 out_put "server.lua: closed handler and removed socket from list" 407 out_put "server.lua: closed handler and removed socket from list"
408 end 408 end
409 handler.ip = function( ) 409 handler.ip = function( )
410 return ip 410 return ip
411 end 411 end
412 handler.serverport = function( ) 412 handler.serverport = function( )
413 return serverport 413 return serverport
414 end 414 end
415 handler.clientport = function( ) 415 handler.clientport = function( )
416 return clientport 416 return clientport
417 end 417 end
418 handler.write = function( data ) 418 handler.write = function( data )
419 if not eol then 419 if not eol then
420 writelen = writelen + 1 420 writelen = writelen + 1
421 writelist[ writelen ] = socket 421 writelist[ writelen ] = socket
422 eol = 0 422 eol = 0
423 end 423 end
424 eol = eol + 1 424 eol = eol + 1
425 writequeue[ eol ] = data 425 writequeue[ eol ] = data
426 end 426 end
427 handler.writequeue = function( ) 427 handler.writequeue = function( )
428 return writequeue 428 return writequeue
429 end 429 end
430 handler.socket = function( ) 430 handler.socket = function( )
431 return socket 431 return socket
432 end 432 end
433 handler.mode = function( ) 433 handler.mode = function( )
434 return mode 434 return mode
435 end 435 end
436 handler.receivedata = function( ) 436 handler.receivedata = function( )
437 local data, err, part = receive( socket, mode ) -- receive data in "mode" 437 local data, err, part = receive( socket, mode ) -- receive data in "mode"
438 if not err or ( err == "timeout" or err == "wantread" ) then -- received something 438 if not err or ( err == "timeout" or err == "wantread" ) then -- received something
439 local data = data or part or "" 439 local data = data or part or ""
440 local count = #data * STAT_UNIT 440 local count = #data * STAT_UNIT
441 rstat = rstat + count 441 rstat = rstat + count
442 receivestat = receivestat + count 442 receivestat = receivestat + count
443 out_put( "server.lua: read data '", data, "', error: ", err ) 443 out_put( "server.lua: read data '", data, "', error: ", err )
444 return dispatch( handler, data, err ) 444 return dispatch( handler, data, err )
445 else -- connections was closed or fatal error 445 else -- connections was closed or fatal error
446 out_put( "server.lua: client ", ip, ":", clientport, " error: ", err ) 446 out_put( "server.lua: client ", ip, ":", clientport, " error: ", err )
447 handler.close( ) 447 handler.close( )
448 disconnect( handler, err ) 448 disconnect( handler, err )
449 writequeue = nil 449 writequeue = nil
450 handler = nil 450 handler = nil
451 return false 451 return false
452 end 452 end
453 end 453 end
454 handler.dispatchdata = function( ) -- this function writes data to handlers 454 handler.dispatchdata = function( ) -- this function writes data to handlers
455 local buffer = table_concat( writequeue, "", 1, eol ) 455 local buffer = table_concat( writequeue, "", 1, eol )
456 local succ, err, byte = send( socket, buffer ) 456 local succ, err, byte = send( socket, buffer )
457 local count = ( succ or 0 ) * STAT_UNIT 457 local count = ( succ or 0 ) * STAT_UNIT
458 sstat = sstat + count 458 sstat = sstat + count
459 sendstat = sendstat + count 459 sendstat = sendstat + count
460 out_put( "server.lua: sended '", buffer, "', bytes: ", succ, ", error: ", err, ", part: ", byte, ", to: ", ip, ":", clientport ) 460 out_put( "server.lua: sended '", buffer, "', bytes: ", succ, ", error: ", err, ", part: ", byte, ", to: ", ip, ":", clientport )
461 if succ then -- sending succesful 461 if succ then -- sending succesful
462 --writequeue = { } 462 --writequeue = { }
463 eol = nil 463 eol = nil
464 writelen = removesocket( writelist, socket, writelen ) -- delete socket from writelist 464 writelen = removesocket( writelist, socket, writelen ) -- delete socket from writelist
465 return true 465 return true
466 elseif byte and ( err == "timeout" or err == "wantwrite" ) then -- want write 466 elseif byte and ( err == "timeout" or err == "wantwrite" ) then -- want write
467 buffer = string_sub( buffer, byte + 1, -1 ) -- new buffer 467 buffer = string_sub( buffer, byte + 1, -1 ) -- new buffer
468 writequeue[ 1 ] = buffer -- insert new buffer in queue 468 writequeue[ 1 ] = buffer -- insert new buffer in queue
469 eol = 1 469 eol = 1
470 return true 470 return true
471 else -- connection was closed during sending or fatal error 471 else -- connection was closed during sending or fatal error
472 out_put( "server.lua: client ", ip, ":", clientport, " error: ", err ) 472 out_put( "server.lua: client ", ip, ":", clientport, " error: ", err )
473 handler.close( ) 473 handler.close( )
474 disconnect( handler, err ) 474 disconnect( handler, err )
475 writequeue = nil 475 writequeue = nil
476 handler = nil 476 handler = nil
477 return false 477 return false
478 end 478 end
479 end 479 end
480 480
481 -- // COMPAT // -- 481 -- // COMPAT // --
482 482
483 handler.getIp = handler.ip 483 handler.getIp = handler.ip
484 handler.getPort = handler.clientport 484 handler.getPort = handler.clientport
485 485
486 socketlist[ socket ] = handler 486 socketlist[ socket ] = handler
487 readlen = readlen + 1 487 readlen = readlen + 1
488 readlist[ readlen ] = socket 488 readlist[ readlen ] = socket
489 489
490 return handler, socket 490 return handler, socket
491 end 491 end
492 492
493 addtimer = function( listener ) 493 addtimer = function( listener )
494 timelistener[ #timelistener + 1 ] = listener 494 timelistener[ #timelistener + 1 ] = listener
495 end 495 end
496 496
497 firetimer = function( listener ) 497 firetimer = function( listener )
498 for i, listener in ipairs( timelistener ) do 498 for i, listener in ipairs( timelistener ) do
499 listener( ) 499 listener( )
500 end 500 end
501 end 501 end
502 502
503 addserver = function( listeners, port, addr, mode, sslctx ) -- this function provides a way for other scripts to reg a server 503 addserver = function( listeners, port, addr, mode, sslctx ) -- this function provides a way for other scripts to reg a server
504 local err 504 local err
505 if type( listeners ) ~= "table" then 505 if type( listeners ) ~= "table" then
506 err = "invalid listener table" 506 err = "invalid listener table"
507 else 507 else
508 for name, func in pairs( listeners ) do 508 for name, func in pairs( listeners ) do
509 if type( func ) ~= "function" then 509 if type( func ) ~= "function" then
510 err = "invalid listener function" 510 err = "invalid listener function"
511 break 511 break
512 end 512 end
513 end 513 end
514 end 514 end
515 if not type( port ) == "number" or not ( port >= 0 and port <= 65535 ) then 515 if not type( port ) == "number" or not ( port >= 0 and port <= 65535 ) then
516 err = "invalid port" 516 err = "invalid port"
517 elseif listener[ port ] then 517 elseif listener[ port ] then
518 err= "listeners on port '" .. port .. "' already exist" 518 err= "listeners on port '" .. port .. "' already exist"
519 elseif sslctx and not luasec then 519 elseif sslctx and not luasec then
520 err = "luasec not found" 520 err = "luasec not found"
521 end 521 end
522 if err then 522 if err then
523 out_error( "server.lua: ", err ) 523 out_error( "server.lua: ", err )
524 return nil, err 524 return nil, err
525 end 525 end
526 addr = addr or "*" 526 addr = addr or "*"
527 local server, err = socket_bind( addr, port ) 527 local server, err = socket_bind( addr, port )
528 if err then 528 if err then
529 out_error( "server.lua: ", err ) 529 out_error( "server.lua: ", err )
530 return nil, err 530 return nil, err
531 end 531 end
532 local handler, err = wrapserver( listeners, server, addr, port, mode, sslctx ) -- wrap new server socket 532 local handler, err = wrapserver( listeners, server, addr, port, mode, sslctx ) -- wrap new server socket
533 if not handler then 533 if not handler then
534 server:close( ) 534 server:close( )
535 return nil, err 535 return nil, err
536 end 536 end
537 server:settimeout( 0 ) 537 server:settimeout( 0 )
538 readlen = readlen + 1 538 readlen = readlen + 1
539 readlist[ readlen ] = server 539 readlist[ readlen ] = server
540 listener[ port ] = listeners 540 listener[ port ] = listeners
541 socketlist[ server ] = handler 541 socketlist[ server ] = handler
542 out_put( "server.lua: new server listener on ", addr, ":", port ) 542 out_put( "server.lua: new server listener on ", addr, ":", port )
543 return true 543 return true
544 end 544 end
545 545
546 removesocket = function( tbl, socket, len ) -- this function removes sockets from a list 546 removesocket = function( tbl, socket, len ) -- this function removes sockets from a list
547 for i, target in ipairs( tbl ) do 547 for i, target in ipairs( tbl ) do
548 if target == socket then 548 if target == socket then
549 len = len - 1 549 len = len - 1
550 table_remove( tbl, i ) 550 table_remove( tbl, i )
551 return len 551 return len
552 end 552 end
553 end 553 end
554 return len 554 return len
555 end 555 end
556 556
557 closeall = function( ) 557 closeall = function( )
558 for sock, handler in pairs( socketlist ) do 558 for sock, handler in pairs( socketlist ) do
559 handler.shutdown( ) 559 handler.shutdown( )
560 handler.close( ) 560 handler.close( )
561 socketlist[ sock ] = nil 561 socketlist[ sock ] = nil
562 end 562 end
563 writelist, readlist, socketlist = { }, { }, { } 563 writelist, readlist, socketlist = { }, { }, { }
564 end 564 end
565 565
566 closesocket = function( socket ) 566 closesocket = function( socket )
567 writelen = removesocket( writelist, socket, writelen ) 567 writelen = removesocket( writelist, socket, writelen )
568 readlen = removesocket( readlist, socket, readlen ) 568 readlen = removesocket( readlist, socket, readlen )
569 socketlist[ socket ] = nil 569 socketlist[ socket ] = nil
570 socket:close( ) 570 socket:close( )
571 end 571 end
572 572
573 loop = function( ) -- this is the main loop of the program 573 loop = function( ) -- this is the main loop of the program
574 --signal_set( "hub", "run" ) 574 --signal_set( "hub", "run" )
575 repeat 575 repeat
576 local read, write, err = socket_select( readlist, writelist, 1 ) -- 1 sec timeout, nice for timers 576 local read, write, err = socket_select( readlist, writelist, 1 ) -- 1 sec timeout, nice for timers
577 for i, socket in ipairs( write ) do -- send data waiting in writequeues 577 for i, socket in ipairs( write ) do -- send data waiting in writequeues
578 local handler = socketlist[ socket ] 578 local handler = socketlist[ socket ]
579 if handler then 579 if handler then
580 handler.dispatchdata( ) 580 handler.dispatchdata( )
581 else 581 else
582 closesocket( socket ) 582 closesocket( socket )
583 out_put "server.lua: found no handler and closed socket (writelist)" -- this should not happen 583 out_put "server.lua: found no handler and closed socket (writelist)" -- this should not happen
584 end 584 end
585 end 585 end
586 for i, socket in ipairs( read ) do -- receive data 586 for i, socket in ipairs( read ) do -- receive data
587 local handler = socketlist[ socket ] 587 local handler = socketlist[ socket ]
588 if handler then 588 if handler then
589 handler.receivedata( ) 589 handler.receivedata( )
590 else 590 else
591 closesocket( socket ) 591 closesocket( socket )
592 out_put "server.lua: found no handler and closed socket (readlist)" -- this can happen 592 out_put "server.lua: found no handler and closed socket (readlist)" -- this can happen
593 end 593 end
594 end 594 end
595 firetimer( ) 595 firetimer( )
596 --collectgarbage "collect" 596 --collectgarbage "collect"
597 until false --signal_get "hub" ~= "run" 597 until false --signal_get "hub" ~= "run"
598 return --signal_get "hub" 598 return --signal_get "hub"
599 end 599 end
600 600
601 ----------------------------------// BEGIN //-- 601 ----------------------------------// BEGIN //--
602 602
603 ----------------------------------// PUBLIC INTERFACE //-- 603 ----------------------------------// PUBLIC INTERFACE //--
604 604
605 return { 605 return {
606 606
607 add = addserver, 607 add = addserver,
608 loop = loop, 608 loop = loop,
609 stats = stats, 609 stats = stats,
610 closeall = closeall, 610 closeall = closeall,
611 addtimer = addtimer, 611 addtimer = addtimer,
612 612
613 } 613 }