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