Some metaserver logic.

This commit is contained in:
wan-may 2023-09-11 22:00:00 -03:00
parent a720ebf173
commit 7396f97433
4 changed files with 112 additions and 16 deletions

10
build.sh Normal file
View File

@ -0,0 +1,10 @@
SRC_DIR="src"
LOVE_DIR="../../love"
BUILD_DIR="build"
cp -r $SRC_DIR/ $BUILD_DIR/
cd $BUILD_DIR/
zip -9 -r vision.love
cat ../../love/love.exe vision.love > vision.exe

View File

@ -1,20 +1,86 @@
local SERVERTIMEOUT = 30
local CLIENTTIMEOUT = 1
local shared = assert( require 'shared' ) local shared = assert( require 'shared' )
local socket = assert( require 'socket' ) local socket = assert( require 'socket' )
local packet = assert( shared.packet )
local udp = assert( socket.udp() ) local udp = assert( socket.udp() )
--Servers broadcast their information here. --Servers broadcast their information here.
--The metaserver builds a list of available servers. ( available meaning, "broadcasted in last ten heartbeats" ) --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? ) --Clients ask the metaserver for this list ( maybe with some filter? )
local servers = {}
local clients = {}
local serverInfo = {} local handlers = setmetatable({
local serverIPs = {}
local clientIPs = {}
local function Parse( packet, ip, port ) 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 end
print( "Starting Metaserver", socket.gettime() ) print( "Starting Metaserver", socket.gettime() )
repeat repeat
read( udp:receivefrom() )
until socket.sleep( 2.0 - (socket.gettime() % 2.0) ) prune( socket.gettime() )
io.flush()
until socket.sleep( 2.0 )

View File

@ -14,7 +14,7 @@ local svInfo = { version = 13,
local server = { tick = 0 } local server = { tick = 0 }
local msIP, msPort local msIP, msPort = "127.0.0.0", 8
local clients = {} local clients = {}
@ -35,7 +35,10 @@ function server.StartLocalClient()
end end
function server.Advertise() function server.Advertise()
udp:sendto( packet.get( packet.serverInfo( svInfo ) ) , msIP, msPort ) print( socket.gettime(), "Advertise." )
packet.metaServer{ padding = "" }
packet.serverInfo( svInfo )
udp:sendto( packet.get() , msIP, msPort )
end end
--Incoming packet. --Incoming packet.
@ -61,10 +64,14 @@ function server.Start()
server.SetIP( socket.dns.toip(socket.dns.gethostname()), 51312 ) server.SetIP( socket.dns.toip(socket.dns.gethostname()), 51312 )
assert( udp:setsockname( tostring( svInfo.ip ), svInfo.port )) assert( udp:setsockname( tostring( svInfo.ip ), svInfo.port ))
server.StartLocalClient() server.StartLocalClient()
print( socket.gettime(), "Start." )
repeat repeat
server.Parse( udp:receivefrom() ) server.Parse( udp:receivefrom() )
server.Advance() server.Advance()
until socket.sleep( 0.1 - (socket.gettime() % 0.1) ) if server.tick % 20 == 0 then
server.Advertise()
end
until socket.sleep( 0.1 )
end end
function server.Advance() function server.Advance()

View File

@ -11,6 +11,7 @@ local function newStruct( t )
ffi.cdef(("typedef struct {uint8_t netname;\n%s;\n} %s;"):format( table.concat( t, ";\n" ), t.name )) ffi.cdef(("typedef struct {uint8_t netname;\n%s;\n} %s;"):format( table.concat( t, ";\n" ), t.name ))
t.ct = ffi.typeof( ffi.new( t.name ) ) t.ct = ffi.typeof( ffi.new( t.name ) )
t.size = ffi.sizeof( t.ct ) t.size = ffi.sizeof( t.ct )
assert( t.size < 500, t.name )
setmetatable( t, mt ) setmetatable( t, mt )
--print( "Packet:", t.name, "Members:", #t + 1, "Size:", t.size, "Alignment:", ffi.alignof( t.ct ) ) --print( "Packet:", t.name, "Members:", #t + 1, "Size:", t.size, "Alignment:", ffi.alignof( t.ct ) )
@ -29,9 +30,15 @@ newStruct{
} }
newStruct{ newStruct{
name = "requestServers", name = "clientInfo",
netname = 22,
"char username[31]",
}
newStruct{
name = "metaServer",
netname = 123, netname = 123,
"char padding[999]" "char padding[300]" --Just a bunch of padding to mitigate amplification.
} }
newStruct{ newStruct{
@ -84,6 +91,12 @@ newStruct{
"char command", "char command",
} }
newStruct{
name = "advertised",
netname = 144,
"uint32_t time",
}
local readBuffer = buffer.new( 1024 ) local readBuffer = buffer.new( 1024 )
function packet.deserialise( str ) function packet.deserialise( str )
readBuffer:set( str ) readBuffer:set( str )
@ -117,7 +130,7 @@ end
local writeBuffer = buffer.new( 1024 ) local writeBuffer = buffer.new( 1024 )
function packet.add( struct, data ) function packet.add( struct, data )
local str = ffi.new( struct.ct, data ) local str = ffi.new( struct.ct, data or 0 )
str.netname = assert( struct.netname ) str.netname = assert( struct.netname )
writeBuffer:putcdata( str, struct.size ) writeBuffer:putcdata( str, struct.size )
return writeBuffer return writeBuffer
@ -129,7 +142,7 @@ end
mt.__call = packet.add mt.__call = packet.add
local testing = true local testing = testing
--TESTS-- --TESTS--
if testing then if testing then