This commit is contained in:
Cloud Wu
2014-07-13 21:02:23 +08:00
parent e963ee6aba
commit 0d1c3a64d1
5 changed files with 63 additions and 35 deletions

View File

@@ -14,7 +14,6 @@ package.cpath = "luaclib/?.so"
]] ]]
local socket = require "clientsocket" local socket = require "clientsocket"
local cjson = require "cjson"
local crypt = require "crypt" local crypt = require "crypt"
local last local last
@@ -61,7 +60,14 @@ local token = {
pass = "password", pass = "password",
} }
local etoken = crypt.desencode(secret, cjson.encode(token)) local function encode_token(token)
return string.format("%s@%s:%s",
crypt.base64encode(token.user),
crypt.base64encode(token.server),
crypt.base64encode(token.pass))
end
local etoken = crypt.desencode(secret, encode_token(token))
local b = crypt.base64encode(etoken) local b = crypt.base64encode(etoken)
socket.writeline(fd, crypt.base64encode(etoken)) socket.writeline(fd, crypt.base64encode(etoken))

View File

@@ -1,5 +1,4 @@
local login = require "gamefw.loginserver" local login = require "gamefw.loginserver"
local json = require "cjson"
local crypt = require "crypt" local crypt = require "crypt"
local skynet = require "skynet" local skynet = require "skynet"
@@ -12,32 +11,51 @@ local server = {
local server_list = {} local server_list = {}
local user_online = {} local user_online = {}
local server_mt = {}
server_mt.__index = server_mt
function server_mt:kick(uid)
skynet.call(self.address, "lua", "kick", self.name, uid)
end
function server_mt:login(uid, secret)
skynet.call(self.address, "lua", "login", self.name, uid, secret)
end
function server.auth_handler(token) function server.auth_handler(token)
token = json.decode(token) -- the token is base64(user)@base64(server):base64(password)
assert(token.user) local user, server, password = token:match("([^@]+)@([^:]+):(.+)")
assert(token.pass == "password") user = crypt.base64decode(user)
return token.server, token.user server = crypt.base64decode(server)
password = crypt.base64decode(password)
assert(password == "password")
return server, user
end end
function server.login_handler(server, uid, secret) function server.login_handler(server, uid, secret)
print(string.format("%s@%s is login, secret is %s", uid, server, crypt.hexencode(secret))) print(string.format("%s@%s is login, secret is %s", uid, server, crypt.hexencode(secret)))
local u = user_online[uid] local u = user_online[uid]
if u then if u then
local gameserver = server_list[u.server] u:kick(uid)
skynet.call(gameserver, "lua", "kick", server, uid)
end end
local gameserver = assert(server_list[server]) assert(user_online[uid] == nil, "kick failed")
skynet.call(gameserver, "lua", "login", server, uid, secret) local gameserver = assert(server_list[server], "Unknown server")
gameserver:login(uid, secret)
user_online[uid] = gameserver
end end
local CMD = {} local CMD = {}
function CMD.register_gate(source, name) function CMD.register_gate(server, address)
server_list[name] = source server_list[server] = setmetatable( { name = server, address = address }, server_mt )
end end
function CMD.logout(source, uid, server) function CMD.logout(uid)
print(string.format("%s@%s is logout", uid, server)) local u = user_online[uid]
if u then
print(string.format("%s@%s is logout", uid, u.name))
user_online[uid] = nil
end
end end
function server.command_handler(command, source, ...) function server.command_handler(command, source, ...)

View File

@@ -140,7 +140,7 @@ handler.error = handler.close
function handler.open(source, conf) function handler.open(source, conf)
login_master = assert(conf.loginserver) login_master = assert(conf.loginserver)
local servername = assert(conf.servername) local servername = assert(conf.servername)
skynet.call(login_master, "lua", "register_gate", servername) skynet.call(login_master, "lua", "register_gate", servername, skynet.self())
end end
@@ -162,7 +162,7 @@ end
function CMD.logout(source) function CMD.logout(source)
local c = agent[source] local c = agent[source]
if c then if c then
skynet.call(login_master, "lua", "logout", c.server, c.uid) skynet.call(login_master, "lua", "logout", c.uid)
if c.fd then if c.fd then
gateserver.closeclient(c.fd) gateserver.closeclient(c.fd)
end end

View File

@@ -729,7 +729,7 @@ lb64encode(lua_State *L) {
} }
int i,j; int i,j;
j=0; j=0;
for (i=0;i<sz-2;i+=3) { for (i=0;i<(int)sz-2;i+=3) {
uint32_t v = text[i] << 16 | text[i+1] << 8 | text[i+2]; uint32_t v = text[i] << 16 | text[i+1] << 8 | text[i+2];
buffer[j] = encoding[v >> 18]; buffer[j] = encoding[v >> 18];
buffer[j+1] = encoding[(v >> 12) & 0x3f]; buffer[j+1] = encoding[(v >> 12) & 0x3f];

View File

@@ -2,18 +2,21 @@ local skynet = require "skynet"
local socket = require "socket" local socket = require "socket"
local crypt = require "crypt" local crypt = require "crypt"
local function launch_slave(auth_handler) local function write(fd, text)
local cmd = {} assert(socket.write(fd, text), "socket error")
end
local function launch_slave(auth_handler)
-- set socket buffer limit (8K) -- set socket buffer limit (8K)
-- If the attacker send large package, close the socket -- If the attacker send large package, close the socket
socket.limit(8192) socket.limit(8192)
function cmd.auth(fd, addr) local function auth(fd, addr)
fd = assert(tonumber(fd))
skynet.error(string.format("connect from %s (fd = %d)", addr, fd)) skynet.error(string.format("connect from %s (fd = %d)", addr, fd))
socket.start(fd) socket.start(fd)
local challenge = crypt.randomkey() local challenge = crypt.randomkey()
socket.write(fd, crypt.base64encode(challenge).."\n") write(fd, crypt.base64encode(challenge).."\n")
local handshake = assert(socket.readline(fd), "socket closed") local handshake = assert(socket.readline(fd), "socket closed")
local clientkey = crypt.base64decode(handshake) local clientkey = crypt.base64decode(handshake)
@@ -21,7 +24,7 @@ local function launch_slave(auth_handler)
error "Invalid client key" error "Invalid client key"
end end
local serverkey = crypt.randomkey() local serverkey = crypt.randomkey()
socket.write(fd, crypt.base64encode(crypt.dhexchange(serverkey)).."\n") write(fd, crypt.base64encode(crypt.dhexchange(serverkey)).."\n")
local secret = crypt.dhsecret(clientkey, serverkey) local secret = crypt.dhsecret(clientkey, serverkey)
@@ -29,7 +32,7 @@ local function launch_slave(auth_handler)
local hmac = crypt.hmac64(challenge, secret) local hmac = crypt.hmac64(challenge, secret)
if hmac ~= crypt.base64decode(response) then if hmac ~= crypt.base64decode(response) then
socket.write(fd, "400 Bad Request\n") write(fd, "400 Bad Request\n")
error "challenge failed" error "challenge failed"
end end
@@ -43,26 +46,27 @@ local function launch_slave(auth_handler)
return ok, server, uid, secret return ok, server, uid, secret
end end
skynet.dispatch("lua", function(_,_,command,...) skynet.dispatch("lua", function(_,_,...)
local f = assert(cmd[command]) skynet.ret(skynet.pack(auth(...)))
skynet.ret(skynet.pack(f(...)))
end) end)
end end
local function accept(conf, s, fd, addr) local function accept(conf, s, fd, addr)
local ok, server, uid, secret = skynet.call(s, "lua", "auth", fd, addr) -- call slave auth
local ok, server, uid, secret = skynet.call(s, "lua", fd, addr)
socket.start(fd)
if not ok then if not ok then
socket.write(fd, "401 Unauthorized\n") write(fd, "401 Unauthorized\n")
error(server) error(server)
end end
socket.start(fd)
local ok, err = pcall(conf.login_handler, server, uid, secret) local ok, err = pcall(conf.login_handler, server, uid, secret)
if ok then if ok then
socket.write(fd, "200 OK\n") err = err or ""
write(fd, "200 "..crypt.base64encode(err).."\n")
else else
socket.write(fd, "406 Not Acceptable\n") write(fd, "406 Not Acceptable\n")
error(err) error(err)
end end
end end
@@ -80,7 +84,7 @@ local function launch_master(conf)
table.insert(slave, source) table.insert(slave, source)
skynet.ret(skynet.pack(nil)) skynet.ret(skynet.pack(nil))
else else
skynet.ret(skynet.pack(conf.command_handler(command, source, ...))) skynet.ret(skynet.pack(conf.command_handler(command, ...)))
end end
end) end)
@@ -104,7 +108,7 @@ local function launch_master(conf)
end) end)
end end
local function login (conf) local function login(conf)
local name = "." .. (conf.name or "login") local name = "." .. (conf.name or "login")
skynet.start(function() skynet.start(function()
local loginmaster = skynet.localname(name) local loginmaster = skynet.localname(name)