Some metaserver logic.
This commit is contained in:
parent
a720ebf173
commit
7396f97433
|
@ -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
|
|
@ -1,20 +1,86 @@
|
|||
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 serverInfo = {}
|
||||
local serverIPs = {}
|
||||
local clientIPs = {}
|
||||
local handlers = setmetatable({
|
||||
|
||||
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
|
||||
|
||||
print( "Starting Metaserver", socket.gettime() )
|
||||
repeat
|
||||
|
||||
until socket.sleep( 2.0 - (socket.gettime() % 2.0) )
|
||||
read( udp:receivefrom() )
|
||||
prune( socket.gettime() )
|
||||
io.flush()
|
||||
until socket.sleep( 2.0 )
|
|
@ -14,7 +14,7 @@ local svInfo = { version = 13,
|
|||
|
||||
local server = { tick = 0 }
|
||||
|
||||
local msIP, msPort
|
||||
local msIP, msPort = "127.0.0.0", 8
|
||||
|
||||
local clients = {}
|
||||
|
||||
|
@ -35,7 +35,10 @@ function server.StartLocalClient()
|
|||
end
|
||||
|
||||
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
|
||||
|
||||
--Incoming packet.
|
||||
|
@ -61,10 +64,14 @@ function server.Start()
|
|||
server.SetIP( socket.dns.toip(socket.dns.gethostname()), 51312 )
|
||||
assert( udp:setsockname( tostring( svInfo.ip ), svInfo.port ))
|
||||
server.StartLocalClient()
|
||||
print( socket.gettime(), "Start." )
|
||||
repeat
|
||||
server.Parse( udp:receivefrom() )
|
||||
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
|
||||
|
||||
function server.Advance()
|
||||
|
|
|
@ -8,9 +8,10 @@ local function newStruct( t )
|
|||
assert( not( packet[ t.name ] or packet[ t.netname ] ))
|
||||
packet[ t.name ] = t
|
||||
packet[ t.netname ] = 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.size = ffi.sizeof( t.ct )
|
||||
assert( t.size < 500, t.name )
|
||||
setmetatable( t, mt )
|
||||
|
||||
--print( "Packet:", t.name, "Members:", #t + 1, "Size:", t.size, "Alignment:", ffi.alignof( t.ct ) )
|
||||
|
@ -29,9 +30,15 @@ newStruct{
|
|||
}
|
||||
|
||||
newStruct{
|
||||
name = "requestServers",
|
||||
name = "clientInfo",
|
||||
netname = 22,
|
||||
"char username[31]",
|
||||
}
|
||||
|
||||
newStruct{
|
||||
name = "metaServer",
|
||||
netname = 123,
|
||||
"char padding[999]"
|
||||
"char padding[300]" --Just a bunch of padding to mitigate amplification.
|
||||
}
|
||||
|
||||
newStruct{
|
||||
|
@ -84,6 +91,12 @@ newStruct{
|
|||
"char command",
|
||||
}
|
||||
|
||||
newStruct{
|
||||
name = "advertised",
|
||||
netname = 144,
|
||||
"uint32_t time",
|
||||
}
|
||||
|
||||
local readBuffer = buffer.new( 1024 )
|
||||
function packet.deserialise( str )
|
||||
readBuffer:set( str )
|
||||
|
@ -117,7 +130,7 @@ end
|
|||
|
||||
local writeBuffer = buffer.new( 1024 )
|
||||
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 )
|
||||
writeBuffer:putcdata( str, struct.size )
|
||||
return writeBuffer
|
||||
|
@ -129,7 +142,7 @@ end
|
|||
|
||||
mt.__call = packet.add
|
||||
|
||||
local testing = true
|
||||
local testing = testing
|
||||
--TESTS--
|
||||
if testing then
|
||||
|
||||
|
|
Loading…
Reference in New Issue