Mercurial > prosody-hg
comparison net/server_event.lua @ 7224:07a4c807a94a
Merge 0.9->0.10
| author | Kim Alvefur <zash@zash.se> |
|---|---|
| date | Wed, 02 Mar 2016 16:32:37 +0100 |
| parents | bdcea2dd33b8 f911f929ca6c |
| children | a74f0b7be6bf 0d9ac472e58c |
comparison
equal
deleted
inserted
replaced
| 7218:6226307f6ac4 | 7224:07a4c807a94a |
|---|---|
| 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 ) |
| 751 end | 752 end |
| 752 end | 753 end |
| 753 | 754 |
| 754 local function setquitting(yes) | 755 local function setquitting(yes) |
| 755 if yes then | 756 if yes then |
| 756 -- Quit now | 757 -- Quit now |
| 757 closeallservers(); | 758 closeallservers(); |
| 758 base:loopexit(); | 759 base:loopexit(); |
| 759 end | 760 end |
| 760 end | 761 end |
| 761 | 762 |
| 762 local function get_backend() | 763 local function get_backend() |
| 763 return base:method(); | 764 return base:method(); |
