2023-09-23 20:36:06 +00:00
|
|
|
--Note, this won't work unless you set up port forwarding!
|
2023-09-12 01:00:00 +00:00
|
|
|
local SERVERTIMEOUT = 30
|
|
|
|
local CLIENTTIMEOUT = 1
|
|
|
|
|
2023-09-19 04:31:42 +00:00
|
|
|
local shared = assert( require '../shared.shared' )
|
2023-09-11 22:44:36 +00:00
|
|
|
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() )
|
2023-09-23 20:36:06 +00:00
|
|
|
local msip = assert( require 'getip' )
|
2023-09-17 03:09:51 +00:00
|
|
|
udp:settimeout(0)
|
2023-09-23 20:36:06 +00:00
|
|
|
local localIP = socket.dns.toip(socket.dns.gethostname())
|
|
|
|
print( "Metaserver local IP:", localIP )
|
|
|
|
assert( udp:setsockname( localIP, shared.metaserver.port ))
|
2023-09-11 22:44:36 +00:00
|
|
|
|
|
|
|
--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 = {}
|
2023-09-17 03:09:51 +00:00
|
|
|
local tick = 0
|
2023-09-12 01:00:00 +00:00
|
|
|
|
2023-12-05 02:02:11 +00:00
|
|
|
local function serverID( ip, port )
|
|
|
|
return ip..":"..port
|
|
|
|
end
|
|
|
|
|
2023-09-12 01:00:00 +00:00
|
|
|
local handlers = setmetatable({
|
|
|
|
|
|
|
|
serverInfo = function( svInfo, ip, port )
|
2023-09-22 04:15:06 +00:00
|
|
|
print( "Server:", ip, port )
|
2023-12-05 02:02:11 +00:00
|
|
|
local id = serverID(ip, port)
|
2023-09-12 01:00:00 +00:00
|
|
|
local t = socket.gettime()
|
2023-12-05 02:02:11 +00:00
|
|
|
if not servers[id] then
|
|
|
|
servers[id] = { ip = ip, port = port, info = svInfo }
|
2023-09-22 04:15:06 +00:00
|
|
|
--NAT punch: the server doesn't know its own external IP
|
|
|
|
--so it contacts a third party (the metaserver) to discover it.
|
|
|
|
--This external IP gets advertised to prospective clients.
|
2023-09-26 03:05:54 +00:00
|
|
|
svInfo.ip.ip = ip
|
2023-09-22 04:15:06 +00:00
|
|
|
svInfo.port = port
|
|
|
|
end
|
2023-12-05 02:02:11 +00:00
|
|
|
servers[id].time = t
|
2023-09-22 04:15:06 +00:00
|
|
|
packet.advertised{ time = t, ip = svInfo.ip, port = svInfo.port }
|
2023-09-17 22:12:13 +00:00
|
|
|
return udp:sendto( packet.get(), ip, port )
|
2023-09-12 01:00:00 +00:00
|
|
|
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 )
|
2023-09-17 03:09:51 +00:00
|
|
|
--[[if ip ~= tostring( clientInfo.ip ) then
|
2023-09-12 01:00:00 +00:00
|
|
|
return print( ip, port, "Client IP mismatch:", clientInfo.ip )
|
2023-09-17 03:09:51 +00:00
|
|
|
end]]
|
|
|
|
|
2023-09-17 22:12:13 +00:00
|
|
|
print( "Server List:", ip, port )
|
2023-09-12 01:00:00 +00:00
|
|
|
|
2023-09-17 03:09:51 +00:00
|
|
|
clients[ip] = clients[ip] or {}
|
2023-09-12 01:00:00 +00:00
|
|
|
|
|
|
|
local t = socket.gettime()
|
|
|
|
clients[ip].time = t
|
2023-09-26 03:05:54 +00:00
|
|
|
|
2023-09-17 22:12:13 +00:00
|
|
|
for svIP, server in pairs( servers ) do
|
|
|
|
print( "", svIP, packet.getString( server.info.svname ))
|
2023-09-12 01:00:00 +00:00
|
|
|
packet.serverInfo( server.info )
|
|
|
|
end
|
|
|
|
|
2023-09-17 22:12:13 +00:00
|
|
|
return udp:sendto( packet.get(), ip, port )
|
2023-09-12 01:00:00 +00:00
|
|
|
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 )
|
|
|
|
for ip, server in pairs(servers) do
|
|
|
|
if server.time < t - SERVERTIMEOUT then
|
2023-09-17 03:09:51 +00:00
|
|
|
print( "Pruning server IP:", ip )
|
2023-09-12 01:00:00 +00:00
|
|
|
servers[ip] = nil
|
|
|
|
end
|
|
|
|
end
|
2023-09-11 22:44:36 +00:00
|
|
|
end
|
|
|
|
|
2023-09-19 05:48:14 +00:00
|
|
|
print( "Starting Metaserver", os.time(), udp:getsockname() )
|
2023-09-19 04:31:42 +00:00
|
|
|
function love.update()
|
2023-09-12 01:00:00 +00:00
|
|
|
read( udp:receivefrom() )
|
|
|
|
prune( socket.gettime() )
|
|
|
|
io.flush()
|
2023-09-17 03:09:51 +00:00
|
|
|
tick = tick + 1
|
2023-09-19 04:31:42 +00:00
|
|
|
end
|