local SERVERTIMEOUT = 30 local CLIENTTIMEOUT = 1 local shared = assert( require 'shared' ) local socket = assert( require 'socket' ) local packet = assert( shared.packet ) local udp = assert( socket.udp() ) --Servers broadcast their information here. --The metaserver builds a list of available servers. ( available meaning, "broadcasted in last ten heartbeats" ) --Clients ask the metaserver for this list ( maybe with some filter? ) local servers = {} local clients = {} local handlers = setmetatable({ serverInfo = function( svInfo, ip, port ) if ip ~= tostring( svInfo.ip ) then return print("Server IP mismatch:", ip, svInfo.ip) end local t = socket.gettime() if not servers[ip] then servers[ip] = { ip = ip, port = port, info = svInfo } end servers[ip].time = t packet.advertised{ time = t } local p = packet.get() for i = 1, 10 do udp:sendto( p, ip, port ) end end, default = function( s, ip, port ) print( ip, port, "Malformed message: ", s ) end, metaServer = function() end, clientInfo = function( clientInfo, ip, port ) if ip ~= tostring( clientInfo.ip ) then return print( ip, port, "Client IP mismatch:", clientInfo.ip ) end if clients[ip] then print( ip, port, "Client request timeout." ) end local t = socket.gettime() clients[ip].time = t for i, server in ipairs( servers ) do packet.serverInfo( server.info ) end local p = packet.get() for i = 1, 10 do udp:sendto( p, ip, port ) end end }, { __index = function(t) return t.default end }) local function read(msg, ip, port) if not msg then return end local msgs, types = packet.deserialise( msg ) if types[1] ~= "metaServer" then print( ip, port, "Dropped packet, no padding." ) return read( udp:receivefrom() ) end for i = 1, #msgs do handlers[ types[i] ]( msgs[i], ip, port ) end return read( udp:receivefrom() ) end local function prune( t ) print( "Pruning", socket.gettime() ) for ip, server in pairs(servers) do if server.time < t - SERVERTIMEOUT then servers[ip] = nil end end end print( "Starting Metaserver", socket.gettime() ) repeat read( udp:receivefrom() ) prune( socket.gettime() ) io.flush() until socket.sleep( 2.0 )