138 local callback = function( event ) |
138 local callback = function( event ) |
139 if EV_TIMEOUT == event then -- timout during connection |
139 if EV_TIMEOUT == event then -- timout during connection |
140 self.fatalerror = "connection timeout" |
140 self.fatalerror = "connection timeout" |
141 self.listener.ontimeout( self ) -- call timeout listener |
141 self.listener.ontimeout( self ) -- call timeout listener |
142 self:_close() |
142 self:_close() |
143 debug( "new connection failed. id:", self, "error:", self.fatalerror ) |
143 debug( "new connection failed. id:", self.id, "error:", self.fatalerror ) |
144 else |
144 else |
145 if plainssl then -- start ssl session |
145 if plainssl then -- start ssl session |
146 self:_start_ssl( self.listener.onconnect ) |
146 self:_start_ssl( self.listener.onconnect ) |
147 else -- normal connection |
147 else -- normal connection |
148 self:_start_session( self.listener.onconnect ) |
148 self:_start_session( self.listener.onconnect ) |
149 end |
149 end |
150 debug( "new connection established. id:", self ) |
150 debug( "new connection established. id:", self.id ) |
151 end |
151 end |
152 self.eventconnect = nil |
152 self.eventconnect = nil |
153 return -1 |
153 return -1 |
154 end |
154 end |
155 self.eventconnect = addevent( base, self.conn, EV_WRITE, callback, cfg.CONNECT_TIMEOUT ) |
155 self.eventconnect = addevent( base, self.conn, EV_WRITE, callback, cfg.CONNECT_TIMEOUT ) |
157 end |
157 end |
158 function interface_mt:_start_session(onconnect) -- new session, for example after startssl |
158 function interface_mt:_start_session(onconnect) -- new session, for example after startssl |
159 if self.type == "client" then |
159 if self.type == "client" then |
160 local callback = function( ) |
160 local callback = function( ) |
161 self:_lock( false, false, false ) |
161 self:_lock( false, false, false ) |
162 --vdebug( "start listening on client socket with id:", self ) |
162 --vdebug( "start listening on client socket with id:", self.id ) |
163 self.eventread = addevent( base, self.conn, EV_READ, self.readcallback, cfg.READ_TIMEOUT ) -- register callback |
163 self.eventread = addevent( base, self.conn, EV_READ, self.readcallback, cfg.READ_TIMEOUT ) -- register callback |
164 onconnect( self ) |
164 onconnect( self ) |
165 self.eventsession = nil |
165 self.eventsession = nil |
166 return -1 |
166 return -1 |
167 end |
167 end |
168 self.eventsession = addevent( base, nil, EV_TIMEOUT, callback, 0 ) |
168 self.eventsession = addevent( base, nil, EV_TIMEOUT, callback, 0 ) |
169 else |
169 else |
170 self:_lock( false ) |
170 self:_lock( false ) |
171 --vdebug( "start listening on server socket with id:", self ) |
171 --vdebug( "start listening on server socket with id:", self.id ) |
172 self.eventread = addevent( base, self.conn, EV_READ, self.readcallback ) -- register callback |
172 self.eventread = addevent( base, self.conn, EV_READ, self.readcallback ) -- register callback |
173 end |
173 end |
174 return true |
174 return true |
175 end |
175 end |
176 function interface_mt:_start_ssl(arg) -- old socket will be destroyed, therefore we have to close read/write events first |
176 function interface_mt:_start_ssl(arg) -- old socket will be destroyed, therefore we have to close read/write events first |
177 --vdebug( "starting ssl session with client id:", self ) |
177 --vdebug( "starting ssl session with client id:", self.id ) |
178 local _ |
178 local _ |
179 _ = self.eventread and self.eventread:close( ) -- close events; this must be called outside of the event callbacks! |
179 _ = self.eventread and self.eventread:close( ) -- close events; this must be called outside of the event callbacks! |
180 _ = self.eventwrite and self.eventwrite:close( ) |
180 _ = self.eventwrite and self.eventwrite:close( ) |
181 self.eventread, self.eventwrite = nil, nil |
181 self.eventread, self.eventwrite = nil, nil |
182 local err |
182 local err |
197 local _, err |
197 local _, err |
198 local attempt = 0 |
198 local attempt = 0 |
199 local maxattempt = cfg.MAX_HANDSHAKE_ATTEMPS |
199 local maxattempt = cfg.MAX_HANDSHAKE_ATTEMPS |
200 while attempt < 1000 do -- no endless loop |
200 while attempt < 1000 do -- no endless loop |
201 attempt = attempt + 1 |
201 attempt = attempt + 1 |
202 debug( "ssl handshake of client with id:", self, "attemp:", attempt ) |
202 debug( "ssl handshake of client with id:"..tostring(self).."attemp:"..attempt ) |
203 if attempt > maxattempt then |
203 if attempt > maxattempt then |
204 self.fatalerror = "max handshake attemps exceeded" |
204 self.fatalerror = "max handshake attemps exceeded" |
205 elseif EV_TIMEOUT == event then |
205 elseif EV_TIMEOUT == event then |
206 self.fatalerror = "timeout during handshake" |
206 self.fatalerror = "timeout during handshake" |
207 else |
207 else |
247 self:_lock( false, true, true ) -- unlock read/write events, but keep interface locked |
247 self:_lock( false, true, true ) -- unlock read/write events, but keep interface locked |
248 self.eventhandshake = addevent( base, self.conn, EV_READWRITE, handshakecallback, cfg.HANDSHAKE_TIMEOUT ) |
248 self.eventhandshake = addevent( base, self.conn, EV_READWRITE, handshakecallback, cfg.HANDSHAKE_TIMEOUT ) |
249 return true |
249 return true |
250 end |
250 end |
251 function interface_mt:_destroy() -- close this interface + events and call last listener |
251 function interface_mt:_destroy() -- close this interface + events and call last listener |
252 debug( "closing client with id:", self ) |
252 debug( "closing client with id:", self.id ) |
253 self:_lock( true, true, true ) -- first of all, lock the interface to avoid further actions |
253 self:_lock( true, true, true ) -- first of all, lock the interface to avoid further actions |
254 local _ |
254 local _ |
255 _ = self.eventread and self.eventread:close( ) -- close events; this must be called outside of the event callbacks! |
255 _ = self.eventread and self.eventread:close( ) -- close events; this must be called outside of the event callbacks! |
256 if self.type == "client" then |
256 if self.type == "client" then |
257 _ = self.eventwrite and self.eventwrite:close( ) |
257 _ = self.eventwrite and self.eventwrite:close( ) |
287 return self._connections |
287 return self._connections |
288 end |
288 end |
289 |
289 |
290 -- Public methods |
290 -- Public methods |
291 function interface_mt:write(data) |
291 function interface_mt:write(data) |
292 --vdebug( "try to send data to client, id/data:", self, data ) |
292 vdebug( "try to send data to client, id/data:", self.id, data ) |
293 data = tostring( data ) |
293 data = tostring( data ) |
294 local len = string_len( data ) |
294 local len = string_len( data ) |
295 local total = len + self.writebufferlen |
295 local total = len + self.writebufferlen |
296 if total > cfg.MAX_SEND_LENGTH then -- check buffer length |
296 if total > cfg.MAX_SEND_LENGTH then -- check buffer length |
297 local err = "send buffer exceeded" |
297 local err = "send buffer exceeded" |
305 self.eventwrite = addevent( base, self.conn, EV_WRITE, self.writecallback, cfg.WRITE_TIMEOUT ) |
305 self.eventwrite = addevent( base, self.conn, EV_WRITE, self.writecallback, cfg.WRITE_TIMEOUT ) |
306 end |
306 end |
307 return true |
307 return true |
308 end |
308 end |
309 function interface_mt:close(now) |
309 function interface_mt:close(now) |
310 debug( "try to close client connection with id:", self ) |
310 debug( "try to close client connection with id:", self.id ) |
311 if self.type == "client" then |
311 if self.type == "client" then |
312 self.fatalerror = "client to close" |
312 self.fatalerror = "client to close" |
313 if ( not self.eventwrite ) or now then -- try to close immediately |
313 if ( not self.eventwrite ) or now then -- try to close immediately |
314 self:_lock( true, true, true ) |
314 self:_lock( true, true, true ) |
315 self:_close() |
315 self:_close() |
318 self:_lock( true, true, false ) |
318 self:_lock( true, true, false ) |
319 debug "closing delayed until writebuffer is empty" |
319 debug "closing delayed until writebuffer is empty" |
320 return nil, "writebuffer not empty, waiting" |
320 return nil, "writebuffer not empty, waiting" |
321 end |
321 end |
322 else |
322 else |
323 debug( "try to close server with id:", self, "args:", now ) |
323 debug( "try to close server with id:", self.id, "args:", now ) |
324 self.fatalerror = "server to close" |
324 self.fatalerror = "server to close" |
325 self:_lock( true ) |
325 self:_lock( true ) |
326 local count = 0 |
326 local count = 0 |
327 for _, item in ipairs( interfacelist( ) ) do |
327 for _, item in ipairs( interfacelist( ) ) do |
328 if ( item.type ~= "server" ) and ( item._server == self ) then -- client/server match |
328 if ( item.type ~= "server" ) and ( item._server == self ) then -- client/server match |
370 end |
370 end |
371 |
371 |
372 |
372 |
373 |
373 |
374 function interface_mt:starttls() |
374 function interface_mt:starttls() |
375 debug( "try to start ssl at client id:", self ) |
375 debug( "try to start ssl at client id:", self.id ) |
376 local err |
376 local err |
377 if not self.sslctx then -- no ssl available |
377 if not self.sslctx then -- no ssl available |
378 err = "no ssl context available" |
378 err = "no ssl context available" |
379 elseif self.usingssl then -- startssl was already called |
379 elseif self.usingssl then -- startssl was already called |
380 err = "ssl already active" |
380 err = "ssl already active" |