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