2023-09-12 01:00:00 +00:00
|
|
|
local SERVERTIMEOUT = 30
|
|
|
|
local CLIENTTIMEOUT = 1
|
|
|
|
|
2023-09-11 22:44:36 +00:00
|
|
|
local shared = assert( require 'shared' )
|
|
|
|
local socket = assert( require 'socket' )
|
2023-09-12 01:00:00 +00:00
|
|
|
local packet = assert( shared.packet )
|
2023-09-11 22:44:36 +00:00
|
|
|
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? )
|
2023-09-12 01:00:00 +00:00
|
|
|
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()
|
2023-09-11 22:44:36 +00:00
|
|
|
|
2023-09-12 01:00:00 +00:00
|
|
|
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
|
2023-09-11 22:44:36 +00:00
|
|
|
|
2023-09-12 01:00:00 +00:00
|
|
|
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
|
2023-09-11 22:44:36 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
print( "Starting Metaserver", socket.gettime() )
|
2023-09-12 01:00:00 +00:00
|
|
|
repeat
|
|
|
|
read( udp:receivefrom() )
|
|
|
|
prune( socket.gettime() )
|
|
|
|
io.flush()
|
|
|
|
until socket.sleep( 2.0 )
|