X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=net%2Fserver_event.lua;h=b467a84dc6c147e6f8ca034fb1e0809d5dcf25a7;hb=4e9ad86f42f78e32d5a983b62277a0552c853a9c;hp=99c3c83bae74d664deea4476ad531df7794fd35d;hpb=ea96097cf969cb91ebf18b0c858bee813069883d;p=prosody.git diff --git a/net/server_event.lua b/net/server_event.lua index 99c3c83b..b467a84d 100644 --- a/net/server_event.lua +++ b/net/server_event.lua @@ -52,6 +52,7 @@ local log = require ("util.logger").init("socket") local function debug(...) return log("debug", ("%s "):rep(select('#', ...)), ...) end +local vdebug = debug; local bitor = ( function( ) -- thx Rici Lake local hasbit = function( x, p ) @@ -139,14 +140,14 @@ do self.fatalerror = "connection timeout" self.listener.ontimeout( self ) -- call timeout listener self:_close() - debug( "new connection failed. id:", self, "error:", self.fatalerror ) + debug( "new connection failed. id:", self.id, "error:", self.fatalerror ) else if plainssl then -- start ssl session self:_start_ssl( self.listener.onconnect ) else -- normal connection self:_start_session( self.listener.onconnect ) end - debug( "new connection established. id:", self ) + debug( "new connection established. id:", self.id ) end self.eventconnect = nil return -1 @@ -158,28 +159,28 @@ do if self.type == "client" then local callback = function( ) self:_lock( false, false, false ) - --vdebug( "start listening on client socket with id:", self ) + --vdebug( "start listening on client socket with id:", self.id ) self.eventread = addevent( base, self.conn, EV_READ, self.readcallback, cfg.READ_TIMEOUT ) -- register callback - onconnect( self ) + self:onconnect() self.eventsession = nil return -1 end self.eventsession = addevent( base, nil, EV_TIMEOUT, callback, 0 ) else self:_lock( false ) - --vdebug( "start listening on server socket with id:", self ) + --vdebug( "start listening on server socket with id:", self.id ) self.eventread = addevent( base, self.conn, EV_READ, self.readcallback ) -- register callback end return true end function interface_mt:_start_ssl(arg) -- old socket will be destroyed, therefore we have to close read/write events first - --vdebug( "starting ssl session with client id:", self ) + --vdebug( "starting ssl session with client id:", self.id ) local _ _ = self.eventread and self.eventread:close( ) -- close events; this must be called outside of the event callbacks! _ = self.eventwrite and self.eventwrite:close( ) self.eventread, self.eventwrite = nil, nil local err - self.conn, err = ssl.wrap( self.conn, self.sslctx ) + self.conn, err = ssl.wrap( self.conn, self._sslctx ) if err then self.fatalerror = err self.conn = nil -- cannot be used anymore @@ -198,7 +199,7 @@ do local maxattempt = cfg.MAX_HANDSHAKE_ATTEMPS while attempt < 1000 do -- no endless loop attempt = attempt + 1 - debug( "ssl handshake of client with id:", self, "attemp:", attempt ) + debug( "ssl handshake of client with id:"..tostring(self).."attemp:"..attempt ) if attempt > maxattempt then self.fatalerror = "max handshake attemps exceeded" elseif EV_TIMEOUT == event then @@ -211,16 +212,16 @@ do self.receive = self.conn.receive local onsomething if "onconnect" == arg then -- trigger listener - onsomething = self.listener.onconnect + onsomething = self.onconnect else - onsomething = self.listener.onsslconnection + onsomething = self.onsslconnection end self:_start_session( onsomething ) debug( "ssl handshake done" ) self.eventhandshake = nil return -1 end - debug( "error during ssl handshake:", err ) + debug( "error during ssl handshake:", err ) if err == "wantwrite" then event = EV_WRITE elseif err == "wantread" then @@ -248,7 +249,7 @@ do return true end function interface_mt:_destroy() -- close this interface + events and call last listener - debug( "closing client with id:", self ) + debug( "closing client with id:", self.id ) self:_lock( true, true, true ) -- first of all, lock the interface to avoid further actions local _ _ = self.eventread and self.eventread:close( ) -- close events; this must be called outside of the event callbacks! @@ -274,6 +275,7 @@ do interfacelist( "delete", self ) return true end + function interface_mt:_lock(nointerface, noreading, nowriting) -- lock or unlock this interface or events self.nointerface, self.noreading, self.nowriting = nointerface, noreading, nowriting return nointerface, noreading, nowriting @@ -288,7 +290,8 @@ do -- Public methods function interface_mt:write(data) - --vdebug( "try to send data to client, id/data:", self, data ) + if self.nowriting then return nil, "locked" end + --vdebug( "try to send data to client, id/data:", self.id, data ) data = tostring( data ) local len = string_len( data ) local total = len + self.writebufferlen @@ -306,7 +309,8 @@ do return true end function interface_mt:close(now) - debug( "try to close client connection with id:", self ) + if self.nointerface then return nil, "locked"; end + debug( "try to close client connection with id:", self.id ) if self.type == "client" then self.fatalerror = "client to close" if ( not self.eventwrite ) or now then -- try to close immediately @@ -319,7 +323,7 @@ do return nil, "writebuffer not empty, waiting" end else - debug( "try to close server with id:", self, "args:", now ) + debug( "try to close server with id:", self.id, "args:", now ) self.fatalerror = "server to close" self:_lock( true ) local count = 0 @@ -353,7 +357,7 @@ do end function interface_mt:ssl() - return self.usingssl + return self._usingssl end function interface_mt:type() @@ -368,22 +372,25 @@ do return self.addr end - + function interface_mt:set_sslctx(sslctx) + self._sslctx = sslctx; + end function interface_mt:starttls() - debug( "try to start ssl at client id:", self ) + debug( "try to start ssl at client id:", self.id ) local err - if not self.sslctx then -- no ssl available + if not self._sslctx then -- no ssl available err = "no ssl context available" - elseif self.usingssl then -- startssl was already called + elseif self._usingssl then -- startssl was already called err = "ssl already active" end if err then debug( "error:", err ) return nil, err end - self.usingssl = true + self._usingssl = true self.startsslcallback = function( ) -- we have to start the handshake outside of a read/write event + self.startsslcallback = nil self:_start_ssl(); self.eventstarthandshake = nil return -1 @@ -443,6 +450,7 @@ do _sslctx = sslctx; -- parameters _usingssl = false; -- client is using ssl; } + interface.id = tostring(interface):match("%x+$"); interface.writecallback = function( event ) -- called on write events --vdebug( "new client write event, id/ip/port:", interface, ip, port ) if interface.nowriting or ( interface.fatalerror and ( "client to close" ~= interface.fatalerror ) ) then -- leave this event @@ -457,7 +465,7 @@ do interface.eventwrite = false return -1 else -- can write :) - if interface.usingssl then -- handle luasec + if interface._usingssl then -- handle luasec if interface.eventreadtimeout then -- we have to read first local ret = interface.readcallback( ) -- call readcallback --vdebug( "tried to read in writecallback, result:", ret ) @@ -467,7 +475,7 @@ do interface.eventwritetimeout = false end end - local succ, err, byte = interface.send( interface.conn, interface.writebuffer, 1, interface.writebufferlen ) + local succ, err, byte = interface.conn:send( interface.writebuffer, 1, interface.writebufferlen ) --vdebug( "write data:", interface.writebuffer, "error:", err, "part:", byte ) if succ then -- writing succesful interface.writebuffer = "" @@ -508,7 +516,7 @@ do end end end - local usingssl, receive = interface._usingssl, interface.receive; + interface.readcallback = function( event ) -- called on read events --vdebug( "new client read event, id/ip/port:", interface, ip, port ) if interface.noreading or interface.fatalerror then -- leave this event @@ -523,7 +531,7 @@ do interface.eventread = nil return -1 else -- can read - if usingssl then -- handle luasec + if interface._usingssl then -- handle luasec if interface.eventwritetimeout then -- ok, in the past writecallback was regged local ret = interface.writecallback( ) -- call it --vdebug( "tried to write in readcallback, result:", ret ) @@ -533,8 +541,8 @@ do interface.eventreadtimeout = nil end end - local buffer, err, part = receive( client, pattern ) -- receive buffer with "pattern" - --vdebug( "read data:", buffer, "error:", err, "part:", part ) + local buffer, err, part = interface.conn:receive( pattern ) -- receive buffer with "pattern" + --vdebug( "read data:", tostring(buffer), "error:", tostring(err), "part:", tostring(part) ) buffer = buffer or part or "" local len = string_len( buffer ) if len > cfg.MAX_READ_LENGTH then -- check buffer length @@ -544,7 +552,7 @@ do interface.eventread = nil return -1 end - if err and ( "timeout" ~= err ) then + if err and ( err ~= "timeout" and err ~= "wantread" ) then if "wantwrite" == err then -- need to read on write event if not interface.eventwrite then -- register new write event if needed interface.eventwrite = addevent( base, interface.conn, EV_WRITE, interface.writecallback, cfg.WRITE_TIMEOUT ) @@ -591,6 +599,7 @@ do fatalerror = false; -- error message nointerface = true; -- lock/unlock parameter } + interface.id = tostring(interface):match("%x+$"); interface.readcallback = function( event ) -- server handler, called on incoming connections --vdebug( "server can accept, id/addr/port:", interface, addr, port ) if interface.fatalerror then