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 cjson = require "cjson"
local crypt = require "crypt"
local last
@@ -61,7 +60,14 @@ local token = {
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)
socket.writeline(fd, crypt.base64encode(etoken))

View File

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

View File

@@ -140,7 +140,7 @@ handler.error = handler.close
function handler.open(source, conf)
login_master = assert(conf.loginserver)
local servername = assert(conf.servername)
skynet.call(login_master, "lua", "register_gate", servername)
skynet.call(login_master, "lua", "register_gate", servername, skynet.self())
end
@@ -162,7 +162,7 @@ end
function CMD.logout(source)
local c = agent[source]
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
gateserver.closeclient(c.fd)
end

View File

@@ -729,7 +729,7 @@ lb64encode(lua_State *L) {
}
int i,j;
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];
buffer[j] = encoding[v >> 18];
buffer[j+1] = encoding[(v >> 12) & 0x3f];

View File

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