X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=net%2Fserver.lua;h=6fe72712ae26e5f7700ff1275ade476132886f4d;hb=4e16323f2a78a2f20bcd75957f2ada27a5d8b90f;hp=773a4232d23c572337c2eb71a0ebffc74afc26b6;hpb=f34b27b198fc707a4cd0eba67f53cee5bb14b85c;p=prosody.git diff --git a/net/server.lua b/net/server.lua index 773a4232..6fe72712 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 // -- @@ -77,6 +75,7 @@ local idfalse local addtimer local closeall local addserver +local getserver local wrapserver local getsettings local closesocket @@ -173,22 +172,30 @@ 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 err = err or "wrong sslctx parameters" out_error( "server.lua: ", err ) - return nil, err + ssl = false end - ssl = true - else - out_put("server.lua: ", "ssl not enabled on ", serverport); + end + if not ssl then + sslctx = false; + if startssl then + out_error( "server.lua: Cannot start ssl on port: ", serverport ) + return nil, "Cannot start ssl, see log for details" + else + out_put("server.lua: ", "ssl not enabled on ", serverport); + end end local accept = socket.accept @@ -244,10 +251,10 @@ wrapserver = function( listeners, socket, ip, serverport, pattern, sslctx, maxco return false end connections = connections + 1 - out_put( "server.lua: accepted new client connection from ", ip, ":", clientport, " to ", serverport) + out_put( "server.lua: accepted new client connection from ", tostring(ip), ":", tostring(clientport), " to ", tostring(serverport)) return dispatch( handler ) elseif err then -- maybe timeout or something else - out_put( "server.lua: error with new client connection: ", err ) + out_put( "server.lua: error with new client connection: ", tostring(err) ) return false end end @@ -318,13 +325,16 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport return shutdown( socket, pattern ) end handler.close = function( forced ) + if not handler then return true; end _readlistlen = removesocket( _readlist, socket, _readlistlen ) _readtimes[ handler ] = nil if bufferqueuelen ~= 0 then if not ( forced or fatalerror ) then handler.sendbuffer( ) if bufferqueuelen ~= 0 then -- try again... - handler.write = nil -- ... but no further writing allowed + if handler then + handler.write = nil -- ... but no further writing allowed + end toclose = true return false end @@ -332,13 +342,15 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport send( socket, table_concat( bufferqueue, "", 1, bufferqueuelen ), 1, bufferlen ) -- forced send end end - shutdown( socket ) + _ = shutdown and shutdown( socket ) socket:close( ) _sendlistlen = removesocket( _sendlist, socket, _sendlistlen ) _socketlist[ socket ] = nil - _writetimes[ handler ] = nil - _closelist[ handler ] = nil - handler = nil + if handler then + _writetimes[ handler ] = nil + _closelist[ handler ] = nil + handler = nil + end socket = nil mem_free( ) if server then @@ -362,14 +374,16 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport _closelist[ handler ] = "send buffer exceeded" -- cannot close the client at the moment, have to wait to the end of the cycle handler.write = idfalse -- dont write anymore return false - elseif not _sendlist[ socket ] then + elseif socket and not _sendlist[ socket ] then _sendlistlen = _sendlistlen + 1 _sendlist[ _sendlistlen ] = socket _sendlist[ socket ] = _sendlistlen end bufferqueuelen = bufferqueuelen + 1 bufferqueue[ bufferqueuelen ] = data - _writetimes[ handler ] = _writetimes[ handler ] or _currenttime + if handler then + _writetimes[ handler ] = _writetimes[ handler ] or _currenttime + end return true end handler.write = write @@ -383,6 +397,10 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport pattern = new or pattern return pattern end + handler.setsend = function ( newsend ) + send = newsend or send + return send + end handler.bufferlen = function( readlen, sendlen ) maxsendlen = sendlen or maxsendlen maxreadlen = readlen or maxreadlen @@ -436,7 +454,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport --out_put( "server.lua: read data '", buffer, "', error: ", err ) return dispatch( handler, buffer, err ) else -- connections was closed or fatal error - out_put( "server.lua: client ", ip, ":", clientport, " error: ", err ) + out_put( "server.lua: client ", tostring(ip), ":", tostring(clientport), " error: ", tostring(err) ) fatalerror = true disconnect( handler, err ) _ = handler and handler.close( ) @@ -450,7 +468,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport sendtraffic = sendtraffic + count _sendtraffic = _sendtraffic + count _ = _cleanqueue and clean( bufferqueue ) - --out_put( "server.lua: sended '", buffer, "', bytes: ", succ, ", error: ", err, ", part: ", byte, ", to: ", ip, ":", clientport ) + --out_put( "server.lua: sended '", buffer, "', bytes: ", tostring(succ), ", error: ", tostring(err), ", part: ", tostring(byte), ", to: ", tostring(ip), ":", tostring(clientport) ) if succ then -- sending succesful bufferqueuelen = 0 bufferlen = 0 @@ -467,10 +485,10 @@ 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 ", ip, ":", clientport, " error: ", err ) + out_put( "server.lua: client ", tostring(ip), ":", tostring(clientport), " error: ", tostring(err) ) fatalerror = true disconnect( handler, err ) - handler.close( ) + _ = handler and handler.close( ) return false end end @@ -478,30 +496,39 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport if sslctx then -- ssl? ssl = true local wrote + local read local handshake = coroutine_wrap( function( client ) -- create handshake coroutine local err for i = 1, 10 do -- 10 handshake attemps + _sendlistlen = ( wrote and removesocket( _sendlist, socket, _sendlistlen ) ) or _sendlistlen + _readlistlen = ( read and removesocket( _readlist, socket, _readlistlen ) ) or _readlistlen + read, wrote = nil, nil _, err = client:dohandshake( ) if not err then - --out_put( "server.lua: ssl handshake done" ) - _sendlistlen = ( wrote and removesocket( _sendlist, socket, _sendlistlen ) ) or _sendlistlen + 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 ) + -- return dispatch( handler ) return true else - out_put( "server.lua: error during ssl handshake: ", err ) + out_put( "server.lua: error during ssl handshake: ", tostring(err) ) if err == "wantwrite" and not wrote then _sendlistlen = _sendlistlen + 1 _sendlist[ _sendlistlen ] = client wrote = true + elseif err == "wantread" and not read then + _readlistlen = _readlistlen + 1 + _readlist [ _readlistlen ] = client + read = true + else + break; end --coroutine_yield( handler, nil, err ) -- handshake not finished coroutine_yield( ) end end - disconnect( handler, "max handshake attemps exceeded" ) - handler.close( true ) -- forced disconnect + disconnect( handler, "ssl handshake failed" ) + _ = handler and handler.close( true ) -- forced disconnect return false -- handshake failed end ) @@ -510,15 +537,20 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport local err socket, err = ssl_wrap( socket, sslctx ) -- wrap socket if err then - out_put( "server.lua: ssl error: ", err ) + out_put( "server.lua: ssl error: ", tostring(err) ) 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" @@ -530,7 +562,7 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport socket, err = ssl_wrap( socket, sslctx ) -- wrap socket --out_put( "server.lua: sslwrapped socket is " .. tostring( socket ) ) if err then - out_put( "server.lua: error while starting tls on client: ", err ) + out_put( "server.lua: error while starting tls on client: ", tostring(err) ) return nil, err -- fatal error end @@ -555,9 +587,12 @@ wrapconnection = function( server, listeners, socket, ip, serverport, clientport handler.starttls = nil needtls = nil + + -- Secure now + ssl = true - handler.receivedata = handler.handshake - handler.dispatchdata = handler.handshake + handler.readbuffer = handshake + handler.sendbuffer = handshake handshake( socket ) -- do handshake end handler.readbuffer = _readbuffer @@ -627,13 +662,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 @@ -650,12 +685,17 @@ addserver = function( listeners, port, addr, pattern, sslctx, maxconnections, st return handler end +getserver = function ( port ) + return _server[ port ]; +end + removeserver = function( port ) local handler = _server[ port ] if not handler then return nil, "no server found on port '" .. tostring( port ) "'" end handler.close( ) + _server[ port ] = nil return true end @@ -708,8 +748,15 @@ stats = function( ) return _readtraffic, _sendtraffic, _readlistlen, _sendlistlen, _timerlistlen end +local dontstop = true; -- thinking about tomorrow, ... + +setquitting = function (quit) + dontstop = not quit; + return; +end + loop = function( ) -- this is the main loop of the program - while true do + while dontstop do local read, write, err = socket_select( _readlist, _sendlist, _selecttimeout ) for i, socket in ipairs( write ) do -- send data waiting in writequeues local handler = _socketlist[ socket ] @@ -744,6 +791,7 @@ loop = function( ) -- this is the main loop of the program socket_sleep( _sleeptime ) -- wait some time --collectgarbage( ) end + return "quitting" end --// EXPERIMENTAL //-- @@ -758,7 +806,7 @@ local wrapclient = function( socket, ip, serverport, listeners, pattern, sslctx, end local addclient = function( address, port, listeners, pattern, sslctx, startssl ) - local client, err = socket.tcp( ) + local client, err = luasocket.tcp( ) if err then return nil, err end @@ -767,7 +815,7 @@ local addclient = function( address, port, listeners, pattern, sslctx, startssl if err then -- try again local handler = wrapclient( client, address, port, listeners ) else - wrapconnection( server, listeners, socket, address, port, "clientport", pattern, sslctx, startssl ) + wrapconnection( nil, listeners, client, address, port, "clientport", pattern, sslctx, startssl ) end end @@ -816,8 +864,9 @@ return { closeall = closeall, addtimer = addtimer, addserver = addserver, + getserver = getserver, getsettings = getsettings, + setquitting = setquitting, removeserver = removeserver, changesettings = changesettings, - }