Handle hash collision in handshake; properly prune old servers from browser.
This commit is contained in:
parent
788b7a11f5
commit
2ca4a77b33
|
@ -58,8 +58,8 @@ function game.update( dt )
|
||||||
if t > 0.1 then
|
if t > 0.1 then
|
||||||
t = 0
|
t = 0
|
||||||
tick = tick + 1
|
tick = tick + 1
|
||||||
server.newPacket()
|
server.newPacket( tick )
|
||||||
assert( server.send( packet.get() ) )
|
assert( server.send() )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -69,10 +69,7 @@ function game.newGame( )
|
||||||
end
|
end
|
||||||
|
|
||||||
function game.disconnect( )
|
function game.disconnect( )
|
||||||
server.newPacket()
|
return scene.mainmenu( server.disconnect( tick ) )
|
||||||
server.disconnect()
|
|
||||||
server.send( packet.get() )
|
|
||||||
return scene.mainmenu( server.disconnect() )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function game.onLoad( params )
|
function game.onLoad( params )
|
||||||
|
|
|
@ -6,7 +6,6 @@ local udp = {}
|
||||||
local packet = assert( require 'shared.packet' )
|
local packet = assert( require 'shared.packet' )
|
||||||
local hash = assert( require 'shared.hash' )
|
local hash = assert( require 'shared.hash' )
|
||||||
|
|
||||||
local token
|
|
||||||
local cxn = assert( socket.udp() )
|
local cxn = assert( socket.udp() )
|
||||||
local mscxn = assert( socket.udp() )
|
local mscxn = assert( socket.udp() )
|
||||||
cxn:settimeout( 0 )
|
cxn:settimeout( 0 )
|
||||||
|
@ -32,19 +31,20 @@ function udp.requestServerList()
|
||||||
end
|
end
|
||||||
|
|
||||||
function udp.newPacket( tick )
|
function udp.newPacket( tick )
|
||||||
packet.get()
|
if udp.token then packet.connected{ token = udp.token, tick = tick or 0 } end
|
||||||
if token then packet.connected{ token = token, tick = tick or 0 } end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function udp.setToken( token )
|
function udp.setToken( token )
|
||||||
token = token
|
print( "Setting server token:", token )
|
||||||
|
udp.token = token
|
||||||
end
|
end
|
||||||
|
|
||||||
function udp.answerChallenge( svNonce )
|
function udp.answerChallenge( svNonce )
|
||||||
local clNonce = hash.rand()
|
local clNonce = hash.rand()
|
||||||
packet.get()
|
packet.get()
|
||||||
packet.clChimo{ nonce = clNonce, hash = hash.hash( clNonce, svNonce ) }
|
packet.clChimo{ nonce = clNonce, hash = hash.hash( clNonce, svNonce ) }
|
||||||
return cxn:send( packet.get() )
|
print( "Received authentication nonce. Reply:", clNonce, svNonce )
|
||||||
|
return udp.send()
|
||||||
end
|
end
|
||||||
|
|
||||||
function udp.isValid( ip, port )
|
function udp.isValid( ip, port )
|
||||||
|
@ -57,17 +57,22 @@ end
|
||||||
function udp.connect( ip, port )
|
function udp.connect( ip, port )
|
||||||
assert( cxn:setpeername( ip, port ) )
|
assert( cxn:setpeername( ip, port ) )
|
||||||
print( "Connection request to:", ip, port )
|
print( "Connection request to:", ip, port )
|
||||||
return udp.send( packet.get( packet.clientInfo{ username = config.plName } ) )
|
return udp.send( packet.clientInfo{ username = config.plName })
|
||||||
end
|
end
|
||||||
|
|
||||||
function udp.disconnect( )
|
function udp.disconnect( tick )
|
||||||
udp.send( packet.get( packet.disconnect{ reason = 0 }))
|
for i = 1, 10 do
|
||||||
|
udp.newPacket( tick )
|
||||||
|
packet.disconnect()
|
||||||
|
udp.send()
|
||||||
|
end
|
||||||
|
udp.setToken()
|
||||||
cxn = assert( socket.udp() )
|
cxn = assert( socket.udp() )
|
||||||
cxn:settimeout( 0 )
|
cxn:settimeout( 0 )
|
||||||
end
|
end
|
||||||
|
|
||||||
function udp.send( s )
|
function udp.send()
|
||||||
return cxn:send( s )
|
return cxn:send( packet.get() )
|
||||||
end
|
end
|
||||||
|
|
||||||
return udp
|
return udp
|
|
@ -144,7 +144,7 @@ end
|
||||||
local metaServerHandlers = setmetatable(
|
local metaServerHandlers = setmetatable(
|
||||||
{
|
{
|
||||||
default = function() end,
|
default = function() end,
|
||||||
heartbeat = serverList.clear,
|
connected = serverList.clear,
|
||||||
serverInfo = serverList.add,
|
serverInfo = serverList.add,
|
||||||
},
|
},
|
||||||
{__index = function( t ) return t.default end })
|
{__index = function( t ) return t.default end })
|
||||||
|
|
|
@ -56,6 +56,8 @@ local handlers = setmetatable({
|
||||||
|
|
||||||
local t = socket.gettime()
|
local t = socket.gettime()
|
||||||
clients[ip].time = t
|
clients[ip].time = t
|
||||||
|
|
||||||
|
packet.connected{ token = 5, tick = tick }
|
||||||
|
|
||||||
for svIP, server in pairs( servers ) do
|
for svIP, server in pairs( servers ) do
|
||||||
print( "", svIP, packet.getString( server.info.svname ))
|
print( "", svIP, packet.getString( server.info.svname ))
|
||||||
|
|
|
@ -9,6 +9,8 @@ assert( mscxn:setpeername( shared.metaserver.ip, shared.metaserver.port ), "Coul
|
||||||
local udp
|
local udp
|
||||||
local io = assert( io )
|
local io = assert( io )
|
||||||
|
|
||||||
|
local CLIENTTIMEOUT = 10
|
||||||
|
|
||||||
local svInfo = packet.serverInfo{ version = 13,
|
local svInfo = packet.serverInfo{ version = 13,
|
||||||
players = 0,
|
players = 0,
|
||||||
capacity = 255,
|
capacity = 255,
|
||||||
|
@ -41,6 +43,7 @@ local handlers = setmetatable({
|
||||||
end
|
end
|
||||||
|
|
||||||
client.tick = msg.tick
|
client.tick = msg.tick
|
||||||
|
client.time = socket.gettime()
|
||||||
server.currentClient = client
|
server.currentClient = client
|
||||||
end,
|
end,
|
||||||
|
|
||||||
|
@ -58,11 +61,17 @@ local handlers = setmetatable({
|
||||||
|
|
||||||
--Client responds to handshake challenge.
|
--Client responds to handshake challenge.
|
||||||
clChimo = function( clChimo, ip, port )
|
clChimo = function( clChimo, ip, port )
|
||||||
|
|
||||||
|
print( "Received handshake response." )
|
||||||
|
|
||||||
|
--No active challenge, don't send anything.
|
||||||
local key = ip..":"..port
|
local key = ip..":"..port
|
||||||
if not connecting[ key ] then
|
if not connecting[ key ] then
|
||||||
print( "Old connection attempt from:", key )
|
print( "Old connection attempt from:", key )
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--Compute session token.
|
||||||
local remoteHash = clChimo.hash
|
local remoteHash = clChimo.hash
|
||||||
local clNonce = clChimo.nonce
|
local clNonce = clChimo.nonce
|
||||||
local svNonce = connecting[key].nonce
|
local svNonce = connecting[key].nonce
|
||||||
|
@ -72,10 +81,14 @@ local handlers = setmetatable({
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--Hash collision.
|
||||||
|
while clients[token] do token = token + 1 end
|
||||||
|
|
||||||
--Successful handshake.
|
--Successful handshake.
|
||||||
print( "Client connected:", ip, port, token )
|
print( "Client connected:", token, port, ip )
|
||||||
clients[ token ] = connecting[ key ]
|
clients[ token ] = connecting[ key ]
|
||||||
clients[ token ].token = token
|
clients[ token ].id = token
|
||||||
|
clients[ token ].time = socket.gettime()
|
||||||
packet.connected{ token = token, tick = server.tick }
|
packet.connected{ token = token, tick = server.tick }
|
||||||
return udp:sendto( packet.get(), ip, port )
|
return udp:sendto( packet.get(), ip, port )
|
||||||
end,
|
end,
|
||||||
|
@ -126,11 +139,9 @@ end
|
||||||
--Incoming packet.
|
--Incoming packet.
|
||||||
function server.Parse( msg, ip, port )
|
function server.Parse( msg, ip, port )
|
||||||
if (not msg) or (#msg < 1) then return end
|
if (not msg) or (#msg < 1) then return end
|
||||||
print( "Parsing:", ip, port, #msg, msg )
|
|
||||||
local msgs, types = packet.deserialise( msg )
|
local msgs, types = packet.deserialise( msg )
|
||||||
if msgs then
|
if msgs then
|
||||||
for i = 1, #msgs do
|
for i = 1, #msgs do
|
||||||
print( "Received: ", types[i], ip, port )
|
|
||||||
if handlers[ types[i] ]( msgs[i], ip, port ) then break end
|
if handlers[ types[i] ]( msgs[i], ip, port ) then break end
|
||||||
end
|
end
|
||||||
server.currentClient = false
|
server.currentClient = false
|
||||||
|
@ -164,14 +175,14 @@ end
|
||||||
|
|
||||||
function server.Advance()
|
function server.Advance()
|
||||||
server.tick = server.tick + 1
|
server.tick = server.tick + 1
|
||||||
|
server.time = socket.gettime()
|
||||||
if server.tick % 100 == 0 then
|
if server.tick % 100 == 0 then
|
||||||
for id, client in pairs( clients ) do
|
for id, client in pairs( clients ) do
|
||||||
packet.get()
|
packet.get()
|
||||||
print( "updating client:", id )
|
|
||||||
packet.connected{ token = id, tick = server.tick }
|
packet.connected{ token = id, tick = server.tick }
|
||||||
udp:sendto( packet.get(), client.ip, client.port )
|
udp:sendto( packet.get(), client.ip, client.port )
|
||||||
|
|
||||||
if server.tick - client.tick > 1000 then
|
if server.time - client.time > CLIENTTIMEOUT then
|
||||||
print( "dropping client:", id )
|
print( "dropping client:", id )
|
||||||
clients[id] = nil
|
clients[id] = nil
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
local math = math
|
local math = math
|
||||||
local bit = assert( require 'bit' )
|
local bit = assert( require 'bit' )
|
||||||
local max = math.huge
|
local max = 65536
|
||||||
math.randomseed( 4 )
|
math.randomseed( 4 )
|
||||||
--hash of a pair of 32-bit numbers
|
--hash of a pair of 32-bit numbers
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -109,6 +109,11 @@ newStruct{
|
||||||
"char reason",
|
"char reason",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newStruct{
|
||||||
|
name = "debugLatency",
|
||||||
|
"uint32_t lastTick",
|
||||||
|
}
|
||||||
|
|
||||||
local readBuffer = buffer.new( 1024 )
|
local readBuffer = buffer.new( 1024 )
|
||||||
function packet.deserialise( str )
|
function packet.deserialise( str )
|
||||||
readBuffer:set( str )
|
readBuffer:set( str )
|
||||||
|
|
Loading…
Reference in New Issue