Connection protocol. Joinable servers!
This commit is contained in:
parent
76beae271c
commit
74e328d86c
|
@ -1,2 +1,3 @@
|
|||
color 0a
|
||||
D:/dev/love/love.exe "./client/"
|
||||
pause
|
|
@ -36,10 +36,28 @@ function connecting.draw()
|
|||
return false
|
||||
end
|
||||
|
||||
function connecting.svChimo( msg )
|
||||
return server.answerChallenge( msg.nonce )
|
||||
end
|
||||
|
||||
function connecting.connected( msg )
|
||||
server.setToken( msg.token )
|
||||
return scene.game()
|
||||
end
|
||||
|
||||
function connecting.keypressed(key, code, isrepeat)
|
||||
if code == "escape" then return scene.browser() end
|
||||
end
|
||||
|
||||
function connecting.read( msg )
|
||||
if not msg then return false end
|
||||
local msgs, types = server.deserialise( msg )
|
||||
for i = 1, #msgs do
|
||||
( connecting[ types[i] ] or print )( msgs[i], ip, port )
|
||||
end
|
||||
return connecting.read( server.receive() )
|
||||
end
|
||||
|
||||
function connecting.update(dt)
|
||||
time = time + dt
|
||||
|
||||
|
@ -49,12 +67,14 @@ function connecting.update(dt)
|
|||
server.connect( ip, port )
|
||||
--return scene.loadScene( scene.game )
|
||||
end
|
||||
return false
|
||||
|
||||
return connecting.read( server.receive() )
|
||||
end
|
||||
|
||||
function connecting:onLoad( params )
|
||||
lg.setCanvas()
|
||||
time = 0
|
||||
attempts = 1
|
||||
params = params or { ip = "8.8.8.8", port = 8 }
|
||||
ip, port = params.ip, params.port
|
||||
return server.isValid( ip, port ) and server.connect( ip, port )
|
||||
|
|
|
@ -4,7 +4,9 @@ local config = assert( require 'config' )
|
|||
|
||||
local udp = {}
|
||||
local packet = assert( require 'shared.packet' )
|
||||
local hash = assert( require 'shared.hash' )
|
||||
|
||||
local token
|
||||
local cxn = assert( socket.udp() )
|
||||
local mscxn = assert( socket.udp() )
|
||||
cxn:settimeout( 0 )
|
||||
|
@ -15,6 +17,8 @@ function udp.receive()
|
|||
return cxn:receive()
|
||||
end
|
||||
|
||||
udp.deserialise = packet.deserialise
|
||||
|
||||
function udp.receiveMeta()
|
||||
return mscxn:receive()
|
||||
end
|
||||
|
@ -27,6 +31,17 @@ function udp.requestServerList()
|
|||
return mscxn:send( packet.get() )
|
||||
end
|
||||
|
||||
function udp.setToken( token )
|
||||
token = token
|
||||
end
|
||||
|
||||
function udp.answerChallenge( svNonce )
|
||||
local clNonce = hash.rand()
|
||||
packet.get()
|
||||
packet.clChimo{ nonce = clNonce, hash = hash.hash( clNonce, svNonce ) }
|
||||
return cxn:send( packet.get() )
|
||||
end
|
||||
|
||||
function udp.isValid( ip, port )
|
||||
local s, e = socket.udp()
|
||||
if s then s, e = s:setpeername( ip, port ) end
|
||||
|
@ -40,7 +55,9 @@ function udp.connect( ip, port )
|
|||
end
|
||||
|
||||
function udp.disconnect( )
|
||||
|
||||
udp.send( packet.get( packet.disconnect{ reason = 0 }))
|
||||
cxn = assert( socket.udp() )
|
||||
cxn:settimeout( 0 )
|
||||
end
|
||||
|
||||
function udp.send( s )
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
color 04
|
||||
D:/dev/love/love.exe "./server/"
|
||||
pause
|
|
@ -20,44 +20,52 @@ local svInfo = packet.serverInfo{ version = 13,
|
|||
|
||||
local clients = {}
|
||||
local connecting = {}
|
||||
local server = { tick = 0, }
|
||||
|
||||
local server = {
|
||||
tick = 0,
|
||||
local handlers = setmetatable({
|
||||
|
||||
clientInfo = function( clientInfo, ip, port )
|
||||
local key = ip..port
|
||||
connecting[key] = connecting[key] or {}
|
||||
local client = connecting[key]
|
||||
local nonce = shared.hash.rand()
|
||||
client.nonce = nonce
|
||||
print( "Received connection request from:", ip, port )
|
||||
print( "Sending authentication nonce:", nonce )
|
||||
packet.svChimo{ nonce = nonce }
|
||||
return udp:sendto( packet.get(), ip, port )
|
||||
end,
|
||||
clChimo = function( clChimo, ip, port )
|
||||
if not connecting[ ip..port ] then
|
||||
return print( "Old connection attempt from:", ip, port )
|
||||
end
|
||||
local remoteHash = clChimo.hash
|
||||
local clNonce = clChimo.nonce
|
||||
local svNonce = connecting[ip..port].nonce
|
||||
local localHash = shared.hash.hash( clNonce, svNonce )
|
||||
if localHash ~= remoteHash then
|
||||
return print( "Hashes differ:", shared.hash.hex( clNonce ), shared.hash.hex( svNonce ) )
|
||||
end
|
||||
print( "Client connected:", ip, port, localHash )
|
||||
clients[ localHash ] = { ip = ip, port = port }
|
||||
packet.connected{ token = localHash }
|
||||
return udp:sendto( packet.get(), ip, port )
|
||||
end,
|
||||
|
||||
clChimo = function( clChimo, ip, port )
|
||||
if not connecting[ ip..port ] then
|
||||
return print( "Old connection attempt from:", ip, port )
|
||||
end
|
||||
local remoteHash = clChimo.hash
|
||||
local clNonce = clChimo.nonce
|
||||
local svNonce = connecting[ip..port].nonce
|
||||
local localHash = shared.hash.hash( clNonce, svNonce )
|
||||
if localHash ~= remoteHash then
|
||||
return print( "Hashes differ:", shared.hash.hex( clNonce ), shared.hash.hex( svNonce ) )
|
||||
end
|
||||
print( "Client connected:", ip, port, localHash )
|
||||
clients[ localHash ] = { ip = ip, port = port }
|
||||
packet.connected{ token = localHash }
|
||||
return udp:sendto( packet.get(), ip, port )
|
||||
end,
|
||||
advertised = function( ack, ip, port )
|
||||
if ip ~= shared.metaserver.ip then return print( "Advertisement acked from rogue address:", ip, port ) end
|
||||
if udp:getsockname() then
|
||||
assert( udp:getsockname() == tostring( ack.ip ) )
|
||||
return print( "Advertised. Address already set." )
|
||||
end
|
||||
print( "Advertised. Setting address:", ack.ip, ack.port )
|
||||
server.SetIP( tostring( ack.ip ), ack.port )
|
||||
end,
|
||||
|
||||
advertised = function( ack, ip, port )
|
||||
print( "Advertised via:", ip, port )
|
||||
end,
|
||||
}
|
||||
|
||||
clientInfo = function( clientInfo, ip, port )
|
||||
local key = ip..port
|
||||
connecting[key] = connecting[key] or {}
|
||||
local client = connecting[key]
|
||||
local nonce = shared.hash.rand()
|
||||
client.nonce = nonce
|
||||
print( "Received connection request from:", ip, port )
|
||||
print( "Sending authentication nonce:", nonce )
|
||||
packet.svChimo{ nonce = nonce }
|
||||
return udp:sendto( packet.get(), ip, port )
|
||||
end,
|
||||
|
||||
|
||||
}, {__index = function() return print end })
|
||||
|
||||
function server.Advertise()
|
||||
print( "Advertise." )
|
||||
|
@ -85,8 +93,8 @@ function server.Parse( msg, ip, port )
|
|||
|
||||
local msgs, types = packet.deserialise( msg )
|
||||
if msgs then for i = 1, #msgs do
|
||||
print( "Received: ", types[i], ip, port );
|
||||
( server[ types[i] ] or print )( msgs[i], ip, port )
|
||||
print( "Received: ", types[i], ip, port )
|
||||
handlers[ types[i] ]( msgs[i], ip, port )
|
||||
end end
|
||||
return server.Parse( udp:receivefrom() ) -- Process other packets.
|
||||
end
|
||||
|
@ -94,13 +102,16 @@ end
|
|||
function server.SetIP( ipString, port )
|
||||
svInfo.ip = shared.ip.fromString( ipString )
|
||||
svInfo.port = port
|
||||
if udp:setsockname( ipString, port ) then
|
||||
local ok, err = udp:setsockname( ipString, port )
|
||||
if ok then
|
||||
print( "Server IP:", udp:getsockname() )
|
||||
return true
|
||||
--Find another port.
|
||||
elseif port < 65536 then
|
||||
print( "Trying port:", port )
|
||||
print( "Could not use port:", ipString, port, err )
|
||||
return server.SetIP( ipString, port + 1 )
|
||||
else
|
||||
print( "Could not use IP: "..ipString )
|
||||
print( "Could not use IP:", ipString, err )
|
||||
return error( "Connection failed." )
|
||||
end
|
||||
end
|
||||
|
@ -109,8 +120,6 @@ end
|
|||
function server.Start()
|
||||
udp = assert( socket.udp() )
|
||||
udp:settimeout(0)
|
||||
server.SetIP( socket.dns.toip(socket.dns.gethostname()), 51312 )
|
||||
print( "Server started:", udp:getsockname() )
|
||||
end
|
||||
|
||||
function server.Advance()
|
||||
|
@ -135,6 +144,7 @@ function love.update( dt )
|
|||
server.Advance()
|
||||
if server.tick % 250 == 0 then
|
||||
server.Advertise()
|
||||
server.Parse( mscxn:receive(), shared.metaserver.ip, shared.metaserver.port )
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
local math = math
|
||||
local bit = assert( require 'bit' )
|
||||
local max = bit.tobit( 0xffffffff )
|
||||
math.randomseed( 4 )
|
||||
--hash of a pair of 32-bit numbers
|
||||
return { hash = bit.bxor, rand = function() return 5 end, hex = bit.tohex }
|
||||
return {
|
||||
hash = bit.bxor,
|
||||
hex = bit.tohex,
|
||||
rand = function()
|
||||
return math.random( 1, max )
|
||||
end, }
|
|
@ -102,8 +102,15 @@ newStruct{
|
|||
}
|
||||
|
||||
newStruct{
|
||||
name = "advertised",
|
||||
"uint32_t time",
|
||||
name = "advertised",
|
||||
"uint32_t time",
|
||||
"ipAddress ip",
|
||||
"uint16_t port",
|
||||
}
|
||||
|
||||
newStruct{
|
||||
name = "disconnect",
|
||||
"uint32_t reason",
|
||||
}
|
||||
|
||||
local readBuffer = buffer.new( 1024 )
|
||||
|
|
Loading…
Reference in New Issue