X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=net%2Fserver.lua;h=54eadbc617b9f0c06861b2d69dca4681ddbdc696;hb=f7f712f889b15132b3466806f337df7a9a427010;hp=9e42b8ff8006fe2d9b5d7c991b71dae905a4c20e;hpb=160dcc8f3a57d5acbca5ccfeff62a59e9f5575e2;p=prosody.git diff --git a/net/server.lua b/net/server.lua index 9e42b8ff..54eadbc6 100644 --- a/net/server.lua +++ b/net/server.lua @@ -1,11 +1,9 @@ ---[[ - - server.lua by blastbeat - - - this script contains the server loop of the program - - other scripts can reg a server here - -]]-- +-- +-- server.lua by blastbeat of the luadch project +-- Re-used here under the MIT/X Consortium License +-- +-- Modifications (C) 2008-2009 Matthew Wild, Waqas Hussain +-- -- // wrapping luadch stuff // -- @@ -159,6 +157,7 @@ _cleanqueue = false -- clean bufferqueue after using _maxclientsperserver = 1000 +_maxsslhandshake = 30 -- max handshake round-trips ----------------------------------// PRIVATE //-- wrapserver = function( listeners, socket, ip, serverport, pattern, sslctx, maxconnections, startssl ) -- this function wraps a server @@ -174,22 +173,51 @@ wrapserver = function( listeners, socket, ip, serverport, pattern, sslctx, maxco local ssl = false if sslctx then + ssl = true if not ssl_newcontext then - return nil, "luasec not found" + out_error "luasec not found" + ssl = false end if type( sslctx ) ~= "table" then out_error "server.lua: wrong server sslctx" - return nil, "wrong server sslctx" + ssl = false end - sslctx, err = ssl_newcontext( sslctx ) - if not sslctx then + local ctx; + ctx, err = ssl_newcontext( sslctx ) + if not ctx then err = err or "wrong sslctx parameters" - out_error( "server.lua: ", err ) - return nil, err + local file; + file = err:match("^error loading (.-) %("); + if file then + if file == "private key" then + file = sslctx.key or "your private key"; + elseif file == "certificate" then + file = sslctx.certificate or "your certificate file"; + end + local reason = err:match("%((.+)%)$") or "some reason"; + if reason == "Permission denied" then + reason = "Check that the permissions allow Prosody to read this file."; + elseif reason == "No such file or directory" then + reason = "Check that the path is correct, and the file exists."; + elseif reason == "system lib" then + reason = "Previous error (see logs), or other system error."; + else + reason = "Reason: "..tostring(reason or "unknown"):lower(); + end + log("error", "SSL/TLS: Failed to load %s: %s", file, reason); + else + log("error", "SSL/TLS: Error initialising for port %d: %s", serverport, err ); + end + ssl = false end - ssl = true - else - out_put("server.lua: ", "ssl not enabled on ", serverport); + sslctx = ctx; + end + if not ssl then + sslctx = false; + if startssl then + log("error", "Failed to listen on port %d due to SSL/TLS to SSL/TLS initialisation errors (see logs)", serverport ) + return nil, "Cannot start ssl, see log for details" + end end local accept = socket.accept @@ -203,6 +231,9 @@ wrapserver = function( listeners, socket, ip, serverport, pattern, sslctx, maxco handler.ssl = function( ) return ssl end + handler.sslctx = function( ) + return sslctx + end handler.remove = function( ) connections = connections - 1 end @@ -219,7 +250,7 @@ wrapserver = function( listeners, socket, ip, serverport, pattern, sslctx, maxco _socketlist[ socket ] = nil handler = nil socket = nil - mem_free( ) + --mem_free( ) out_put "server.lua: closed server handler and removed sockets from list" end handler.ip = function( ) @@ -270,6 +301,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport local ssl local dispatch = listeners.incoming or listeners.listener + local status = listeners.status local disconnect = listeners.disconnect local bufferqueue = { } -- buffer array @@ -309,6 +341,9 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport handler.ssl = function( ) return ssl end + handler.sslctx = function ( ) + return sslctx + end handler.send = function( _, data, i, j ) return send( socket, data, i, j ) end @@ -336,6 +371,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport send( socket, table_concat( bufferqueue, "", 1, bufferqueuelen ), 1, bufferlen ) -- forced send end end + if not handler then return true; end _ = shutdown and shutdown( socket ) socket:close( ) _sendlistlen = removesocket( _sendlist, socket, _sendlistlen ) @@ -346,7 +382,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport handler = nil end socket = nil - mem_free( ) + --mem_free( ) if server then server.remove( ) end @@ -445,10 +481,10 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport readtraffic = readtraffic + count _readtraffic = _readtraffic + count _readtimes[ handler ] = _currenttime - --out_put( "server.lua: read data '", buffer, "', error: ", err ) + --out_put( "server.lua: read data '", buffer:gsub("[^%w%p ]", "."), "', error: ", err ) return dispatch( handler, buffer, err ) else -- connections was closed or fatal error - out_put( "server.lua: client ", tostring(ip), ":", tostring(clientport), " error: ", tostring(err) ) + out_put( "server.lua: client ", tostring(ip), ":", tostring(clientport), " read error: ", tostring(err) ) fatalerror = true disconnect( handler, err ) _ = handler and handler.close( ) @@ -456,13 +492,19 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport end end local _sendbuffer = function( ) -- this function sends data - local buffer = table_concat( bufferqueue, "", 1, bufferqueuelen ) - local succ, err, byte = send( socket, buffer, 1, bufferlen ) - local count = ( succ or byte or 0 ) * STAT_UNIT - sendtraffic = sendtraffic + count - _sendtraffic = _sendtraffic + count - _ = _cleanqueue and clean( bufferqueue ) - --out_put( "server.lua: sended '", buffer, "', bytes: ", tostring(succ), ", error: ", tostring(err), ", part: ", tostring(byte), ", to: ", tostring(ip), ":", tostring(clientport) ) + local succ, err, byte, buffer, count; + local count; + if socket then + buffer = table_concat( bufferqueue, "", 1, bufferqueuelen ) + succ, err, byte = send( socket, buffer, 1, bufferlen ) + count = ( succ or byte or 0 ) * STAT_UNIT + sendtraffic = sendtraffic + count + _sendtraffic = _sendtraffic + count + _ = _cleanqueue and clean( bufferqueue ) + --out_put( "server.lua: sended '", buffer, "', bytes: ", tostring(succ), ", error: ", tostring(err), ", part: ", tostring(byte), ", to: ", tostring(ip), ":", tostring(clientport) ) + else + succ, err, count = false, "closed", 0; + end if succ then -- sending succesful bufferqueuelen = 0 bufferlen = 0 @@ -479,7 +521,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport _writetimes[ handler ] = _currenttime return true else -- connection was closed during sending or fatal error - out_put( "server.lua: client ", tostring(ip), ":", tostring(clientport), " error: ", tostring(err) ) + out_put( "server.lua: client ", tostring(ip), ":", tostring(clientport), " write error: ", tostring(err) ) fatalerror = true disconnect( handler, err ) _ = handler and handler.close( ) @@ -493,7 +535,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport local read local handshake = coroutine_wrap( function( client ) -- create handshake coroutine local err - for i = 1, 10 do -- 10 handshake attemps + for i = 1, _maxsslhandshake do _sendlistlen = ( wrote and removesocket( _sendlist, socket, _sendlistlen ) ) or _sendlistlen _readlistlen = ( read and removesocket( _readlist, socket, _readlistlen ) ) or _readlistlen read, wrote = nil, nil @@ -502,7 +544,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport out_put( "server.lua: ssl handshake done" ) handler.readbuffer = _readbuffer -- when handshake is done, replace the handshake function with regular functions handler.sendbuffer = _sendbuffer - -- return dispatch( handler ) + _ = status and status( handler, "ssl-handshake-complete" ) return true else out_put( "server.lua: error during ssl handshake: ", tostring(err) ) @@ -522,7 +564,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport end end disconnect( handler, "ssl handshake failed" ) - handler.close( true ) -- forced disconnect + _ = handler and handler.close( true ) -- forced disconnect return false -- handshake failed end ) @@ -532,14 +574,19 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport socket, err = ssl_wrap( socket, sslctx ) -- wrap socket if err then out_put( "server.lua: ssl error: ", tostring(err) ) - mem_free( ) + --mem_free( ) return nil, nil, err -- fatal error end socket:settimeout( 0 ) handler.readbuffer = handshake handler.sendbuffer = handshake - handshake( socket ) -- do handshake + handshake( socket ) -- do handshake + if not socket then + return nil, nil, "ssl handshake failed"; + end else + -- We're not automatically doing SSL, so we're not secure (yet) + ssl = false handler.starttls = function( now ) if not now then --out_put "server.lua: we need to do tls, but delaying until later" @@ -576,6 +623,9 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport handler.starttls = nil needtls = nil + + -- Secure now + ssl = true handler.readbuffer = handshake handler.sendbuffer = handshake @@ -629,7 +679,7 @@ closesocket = function( socket ) _readlistlen = removesocket( _readlist, socket, _readlistlen ) _socketlist[ socket ] = nil socket:close( ) - mem_free( ) + --mem_free( ) end ----------------------------------// PUBLIC //-- @@ -648,13 +698,13 @@ addserver = function( listeners, port, addr, pattern, sslctx, maxconnections, st err = "luasec not found" end if err then - out_error( "server.lua: ", err ) + out_error( "server.lua, port ", port, ": ", err ) return nil, err end addr = addr or "*" local server, err = socket_bind( addr, port ) if err then - out_error( "server.lua: ", err ) + out_error( "server.lua, port ", port, ": ", err ) return nil, err end local handler, err = wrapserver( listeners, server, addr, port, pattern, sslctx, maxconnections, startssl ) -- wrap new server socket @@ -678,9 +728,10 @@ end removeserver = function( port ) local handler = _server[ port ] if not handler then - return nil, "no server found on port '" .. tostring( port ) "'" + return nil, "no server found on port '" .. tostring( port ) .. "'" end handler.close( ) + _server[ port ] = nil return true end @@ -697,11 +748,11 @@ closeall = function( ) _sendlist = { } _timerlist = { } _socketlist = { } - mem_free( ) + --mem_free( ) end getsettings = function( ) - return _selecttimeout, _sleeptime, _maxsendlen, _maxreadlen, _checkinterval, _sendtimeout, _readtimeout, _cleanqueue, _maxclientsperserver + return _selecttimeout, _sleeptime, _maxsendlen, _maxreadlen, _checkinterval, _sendtimeout, _readtimeout, _cleanqueue, _maxclientsperserver, _maxsslhandshake end changesettings = function( new ) @@ -717,6 +768,7 @@ changesettings = function( new ) _readtimeout = tonumber( new.readtimeout ) or _readtimeout _cleanqueue = new.cleanqueue _maxclientsperserver = new._maxclientsperserver or _maxclientsperserver + _maxsslhandshake = new._maxsslhandshake or _maxsslhandshake return true end @@ -769,7 +821,7 @@ loop = function( ) -- this is the main loop of the program _currenttime = os_time( ) if os_difftime( _currenttime - _timer ) >= 1 then for i = 1, _timerlistlen do - _timerlist[ i ]( ) -- fire timers + _timerlist[ i ]( _currenttime ) -- fire timers end _timer = _currenttime end