tdengine 0.1.2

game server for Rust
Documentation
-- global_comm.lua
-- Created by wugd
-- 处理通信消息的派发

-- flag标志为1或0,分别代表打开所有消息和关闭所有消息
-- flag为table,则代表打开指定玩家rid的消息
-- gate logic client
local debug_flag = 1
local send_debug_flag = 1
local new_connection_callback = {}
local socket_cookie_map = {}
local msg_filter = {}
local max_online_num = 1000

-- 发起 socket 连接的回调
local function socket_connect_callback(cookie, fd, client_ip)
    local cookie_info = socket_cookie_map[cookie]
    if not cookie_info then
        -- 没有记录该 cookie 的发起连接请求
        close_fd(fd)
        return
    end

    -- 删除缓存记录
    socket_cookie_map[cookie] = nil

    -- 解除对新连接的关注
    unregister_new_connection_callback(cookie)

    local agent = fd
    if fd ~= -1 then
        agent = clone_object(AGENT_TDCLS)
        -- 设置验证
        agent:set_authed(true)
        -- 设置端口与 agent 的映射关系
        agent:set_port_no(fd)
    end

    -- 若有回调,则调用之
    local f, arg = cookie_info["callback"], cookie_info["arg"]
    if type(f) == "function" then
        f(agent, arg)
    end
end

-- 更新玩家每次操作的时间(在发送CMD消息时调用)
local function update_operation_time(agent)
    -- 判断该agent是否玩家
    if agent:is_user() then
        agent:set_temp("last_operation_time", os.time())
    end
end

-- 注册新连接的回调
function register_new_connection_callback(cookie, f)
    new_connection_callback[cookie] = f
end

-- 注销新连接的回调
function unregister_new_connection_callback(cookie)
    new_connection_callback[cookie] = nil
end

-- 连接断开的回调
function cmd_connection_lost(port_no)
    trace("断开连接(%d)\n", port_no)
    -- 取得该端口对应的 agent
    local agent = find_agent_by_port(port_no)
    if agent == nil then
        -- 不存在对应的 agent,不处理
        do return end
    end
    -- 通知 agent 连接断开
    agent:connection_lost()
end

function get_server_type(client_ip, server_port)
    if SERVER_TYPE == "logic" then
        -- for _,value in ipairs(GATE_SERVER) do
        --     if string.match(client_ip, value) then
        --         return SERVER_TYPE_GATE
        --     end

        -- end
        return SERVER_TYPE_GATE
    elseif SERVER_TYPE == "gate" and server_port == tonumber(GATE_LOGIC_PORT) then
        -- for _,value in ipairs(LOGIC_SERVER) do
        --     if string.match(client_ip, value) then
        --         return SERVER_TYPE_LOGIC
        --     end
        -- end
        return SERVER_TYPE_LOGIC
    end
    return SERVER_TYPE_CLIENT
end

-- 收到新连接
function cmd_new_connection(cookie, fd, client_ip, server_port)
    trace("收到新连接(%d)。端口(%d), 客户端地址(%s), new connect info\n", fd, server_port, client_ip)
    local f = new_connection_callback[cookie]
    if type(f) == "function" then
        -- 若该连接有回调,则调用之
        f(cookie, fd, client_ip)
        return
    end

    local agent = clone_object(AGENT_TDCLS)
    -- 设置端口与 agent 的映射关系
    agent:set_port_no(fd)
    agent:set_client_ip(client_ip)
    local server_type = get_server_type(client_ip, server_port)
    if server_type == SERVER_TYPE_GATE or server_type == SERVER_TYPE_LOGIC then
        -- 现在暂时不需要验证
        agent:set_authed(true)
        agent:set_server_type(server_type)
    else
        local server_fd = get_logic_fd()
        if SERVER_TYPE == SERVER_GATE and server_fd ~= -1 then
            agent:set_server_type(server_type)
            set_port_map(server_fd, fd)
        else
            trace("no logic server to accept so close the port")
            agent:connection_lost()
        end

        --超过最高在线
        if get_real_agent_count() > max_online_num then
            agent:connection_lost()
        end
    end
end

-- 是否输出消息trace
function debug_on(flag, rid)
    -- 开启或关闭所有消息
    if not rid or type(rid) ~= "string" then
        if not flag or flag == 0 then
            debug_flag = 0
        else
            debug_flag = 1
        end

    -- 对指定玩家开启或关闭所有消息
    else
        if not flag or flag == 0 then
            if type(debug_flag) == "table" then
                debug_flag[rid] = nil
                if sizeof(debug_flag) <= 0 then
                    debug_flag  = 0
                end
            end
        else
            if type(debug_flag) ~= "table" then
                debug_flag = {}
            end
            debug_flag[rid] = true
        end
    end
end

-- 发送消息是否输出 trace
function send_debug_on(flag, rid)
    -- 开启或关闭所有消息
    if not rid or type(rid) ~= "string" then
        if not flag or flag == 0 then
            send_debug_flag = 0
        else
            send_debug_flag = 1
        end

    -- 对指定玩家开启或关闭所有消息
    else
        if not flag or flag == 0 then
            if type(send_debug_flag) == "table" then
                send_debug_flag[rid] = nil
                if sizeof(send_debug_flag) <= 0 then
                    send_debug_flag  = 0
                end
            end
        else
            if type(send_debug_flag) ~= "table" then
                send_debug_flag = {}
            end
            send_debug_flag[rid] = true
        end
    end
end

function get_send_debug_flag()
    return send_debug_flag
end

function get_debug_flag()
    return debug_flag
end

function get_message_manage_type(message, server_type)
    local msg_type = get_message_type(message)
    if msg_type == "" then
        return MESSAGE_DISCARD
    end
    if SERVER_TYPE == SERVER_CLIENT then
        return MESSAGE_MANAGE
    end

    if server_type == SERVER_TYPE_CLIENT then
        if msg_type == MESSAGE_GATE or msg_type == MESSAGE_SERVER then
            return MESSAGE_MANAGE
        else
            return MESSAGE_FORWARD
        end
    elseif server_type == SERVER_TYPE_GATE then
        return MESSAGE_MANAGE
    elseif server_type == SERVER_TYPE_LOGIC then
        if msg_type == MESSAGE_LOGIC or msg_type == MESSAGE_SERVER then
            return MESSAGE_MANAGE
        else
            return MESSAGE_FORWARD
        end
    else
        assert(false, "unknow message type")
    end
end

function oper_message(agent, message, msg_buf)
    local name, args = msg_buf:msg_to_table()
    assert(name == message)
    local flag = get_debug_flag()
    if (type(flag) == "number" and flag == 1) or
           (type(flag) == "table" and self:is_user() and flag[self:get_rid()]) then
        trace("------------- msg : %s -------------\n%o\n", message, args)
    end
    
    local message_handler = _G[message]
    if not message_handler then
        trace("global_dispatch_command message_handler : %o 未定义消息处理函数!\n", message)
        return
    end

    -- 为客户端,直接执行消息处理函数
    message_handler(agent, unpack(args or {}))
end

-- 派发消息的入口函数
function global_dispatch_command(port_no, message, buffer)
    

    -- 判断是否已存在对应的 agent
    local agent = find_agent_by_port(port_no)
    -- trace("------- my agent = %o ---------", agent)
    if not agent or
       (not agent:is_authed() and message ~= "cmd_internal_auth") then
        -- 若找不到 agent,且该消息不为验证消息,则认为是非法连接,不处理
        trace("非法连接(%d)\n 消息为(%o)", port_no, message)
        if not agent then
            trace("端口绑定的对象不存在")
        end
        if is_object(agent) then
            agent:print_fd_info()
            destruct_object(agent)
        else 
            close_fd(port_no)
        end
        do return end
    end


    local mm_type = get_message_manage_type(message, agent:get_server_type())
    if mm_type == MESSAGE_DISCARD then
        trace("------------- discard port_no is %o, cmd : %s -------------\n", port_no, message)
        del_message(buffer)
        return 
    end

    if agent:get_server_type() == SERVER_TYPE_CLIENT and CHECK_PACK and not agent:check_next_client(buffer:get_seq_fd()) then
        trace("package check failed %o kick the socket", agent:get_ob_id())
        trace("agent:get_server_type() = %o ", agent:get_server_type())
        agent:connection_lost()
        del_message(buffer)
        return
    end
    if mm_type == MESSAGE_FORWARD then
        if agent:get_server_type() == SERVER_TYPE_LOGIC then
            local clientAgent = find_agent_by_port(buffer:get_seq_fd())
            if clientAgent then
               clientAgent:forward_message(buffer) 
            end
        else
            agent:forward_logic_message(buffer)
        end
        del_message(buffer)
        return
    elseif agent:get_server_type() == SERVER_TYPE_GATE then
        local logic_agent = find_agent_by_port(buffer:get_seq_fd() + 0x10000)
        if logic_agent then
            agent = logic_agent
        end
    end

    if is_function(msg_filter[message]) then
        msg_filter[message](agent, buffer)
        del_message(buffer)
        return
    end

    oper_message(agent, message, buffer)
    del_message(buffer)

    if agent:is_user() then
        update_operation_time(agent)
        if PACKAGE_STATD then
            PACKAGE_STATD.on_user_recv_package(agent)
        end
    end
end

-- 取得DB的返回值
function msg_db_result(cookie, ret, result_list)
    -- 通知 DB_D 收到结果
    if type(result_list) == "table" then
        DB_D.notify_operation_result(cookie, ret, unpack(result_list))
    else
        DB_D.notify_operation_result(cookie, ret, result_list)
    end
end

-- 取得Redis的返回值
function msg_redis_result(cookie, value)
    REDIS_D.notify_operation_result(cookie, value)
end


-- 注册消息的过滤器
function register_msg_filter(msg, f)
    msg_filter[msg] = f
end

-- 发起一个连接
-- 异常操作
function socket_connect(ip, port, timeout, callback, arg)
    local cookie = new_cookie()

    -- 缓存该连接对象的 cookie
    socket_cookie_map[cookie] = {
        ip       = ip,
        port     = port,
        timeout  = timeout,
        callback = callback,
        arg      = arg,
    }

    -- 注册关注该 cookie 的新连接创建
    register_new_connection_callback(cookie, socket_connect_callback)

    -- 发起连接创建的请求
    return (new_connect(ip, port, timeout, cookie))
end

--query is get data, body is post data
function http_server_msg_recv(cookie, url, body, remote_host)
    cookie = tonumber(cookie)
    trace("http_server_msg_recv args is %o", {cookie, route, query, body, remote_host})
    http_server_respone(cookie, "hello world from lua")
end

function http_client_msg_respone(cookie, success, body)
    cookie = tonumber(cookie)
    success = success == "true" or success == "1"
    trace("http_client_msg_respone args is %o", {cookie, success, body})
end

function set_max_online_num(num)
    max_online_num = num
end

function get_max_online_num()
    return max_online_num
end