tdengine 0.1.2

game server for Rust
Documentation
-- agent.lua
-- Created by wugd
-- 连接对象基类

-- fport_no 为转发的端口号,用于网关服,逻辑服
-- port_no 为真实的端口号

-- 创建类模板
AGENT_TDCLS = tdcls();
AGENT_TDCLS.name = "AGENT_TDCLS";

-- 构造函数
function AGENT_TDCLS:create()
    self.port_no  = -1;
    self.fport_no = -1;
    self.timer_id = -1;
    self.client_ip = -1;
    self.server_type = 0;
    self.client_seq = -1;
    self.server_seq = 234;

    self.authed = false;
    -- 保存agent数据
    self.data = {};
end

function AGENT_TDCLS:calc_next_seq(seq)
    seq = seq + 111;
    seq = bit32.band(seq, 0xFFFF);
    return seq;
end

function AGENT_TDCLS:get_next_server_seq()
    self.server_seq = self:calc_next_seq(self.server_seq)
    return self.server_seq
end

function AGENT_TDCLS:check_next_client(seq)
    if self.client_seq < 0 then
        self.client_seq = seq
    else
        self.client_seq = self:calc_next_seq(self.client_seq)
    end
    return self.client_seq == seq
end

function AGENT_TDCLS:set_client_seq(seq)
    self.client_seq = seq
end

function AGENT_TDCLS:close_agent()
    if self.fport_no ~= -1 then
        remove_port_agent(self.fport_no);
    elseif self.port_no ~= -1 then
        remove_port_agent(self.port_no);
        close_fd(self.port_no)
    end
    self.fport_no = -1
    self.port_no = -1
end

-- 析造函数
function AGENT_TDCLS:destruct()
    self:close_agent()
    if is_valid_timer(self.timer_id) then
        delete_timer(self.timer_id);
        self.timer_id = -1;
    end
end

-- 生成对象的唯一ID
function AGENT_TDCLS:get_ob_id()
    return (string.format("AGENT_TDCLS:%s:%s", save_string(self.fport_no), save_string(self.port_no)));
end

-- 定义公共接口,按照字母顺序排序

-- 连接断开
function AGENT_TDCLS:connection_lost()
    destruct_object(self)
end

-- 获取数据
function AGENT_TDCLS:get_data(key)
    return self.data[key];
end

-- 保存数据
function AGENT_TDCLS:set_data(key, value)
    self.data[key] = value;
end

function AGENT_TDCLS:get_fport_no()
    return self.fport_no
end

-- 取得连接号
function AGENT_TDCLS:get_port_no()
    return self.port_no;
end

function AGENT_TDCLS:get_uni_port_no()
    if self.fport_no == -1 then
        return self.port_no
    else
        return self.fport_no
    end
end

-- 取得该 agent 是否通过验证
function AGENT_TDCLS:is_authed()
    return self.authed;
end

-- 转接通讯端口到另一个对象上
function AGENT_TDCLS:relay_comm(to_comm)
    -- 取消本对象的端口-对象的映射
    if self.port_no == -1 then
        return;
    end
    
    to_comm:close_agent()
    -- 绑定到另一个连接 ob 上
    to_comm:set_authed(true)
    to_comm:set_all_port_no(self.fport_no, self.port_no)
    to_comm:set_client_ip(self:get_client_ip())

    -- 清除本对象信息
    self.port_no = -1
    self.fport_no = -1
end

function AGENT_TDCLS:forward_message(msg)
    local port_no = self.port_no;
    if port_no == -1 then
        return;
    end

    if SERVER_TYPE == "gate" and self.server_type == SERVER_TYPE_CLIENT then
        msg:set_seq_fd(self:get_next_server_seq())
    end

    pcall(forward_to_port, port_no, msg);
end

function AGENT_TDCLS:send_net_msg(net_msg)
    if self.fport_no ~= -1 then
        net_msg:set_seq_fd(self.fport_no)
    elseif SERVER_TYPE == "gate" and self.server_type == SERVER_TYPE_CLIENT then
        net_msg:set_seq_fd(self:get_next_server_seq())
    end

    -- 缓存中没消息,直接发送该消息
    local _, ret = pcall(send_msg_to_port, self.port_no, net_msg);
    return ret
end

-- 发送消息
function AGENT_TDCLS:send_message(msg, ...)
    -- trace("###################1 msg : %s ###################\n%o\n", msg, { ... });
    local port_no = self.port_no;
    if port_no == -1 then
        return;
    end

    local net_msg = pack_message(msg, ...)
    if SERVER_TYPE == "client" and get_network_seq_id then
        net_msg:set_seq_fd(get_network_seq_id(port_no))
    end
    local ret = self:send_net_msg(net_msg)

    if ret == 0 then
        -- 发送成功
        local flag = get_send_debug_flag();
        if (type(flag) == "number" and flag == 1) or
           (type(flag) == "table" and self:is_user() and flag[self:get_rid()]) then
            trace("################### cmd : %s ###################\n%o\n",
                  msg, { ... });
        end
    elseif self:is_user() then
        -- 表示发送缓存区已满,若是玩家直接关闭该连接
        if ret == 2 then
            trace("玩家 socket 发送缓存区已满,断开该连接。\n");
            set_timer(10, self.connection_lost, self);
            write_log(string.format("Error: socket 发送缓存区已满,断开该连接。玩家(%s),send_message(%s)\n",
                                     self:query("rid"), tostring(msg) ));
        end
    end

    del_message(net_msg)
    return;
end

-- 发送打包好的消息
function AGENT_TDCLS:send_raw_message(msg_buf)
    local port_no = self.port_no;
    if port_no == -1 then
        return;
    end

    local net_msg = pack_raw_message(msg_buf)
    local ret = self:send_net_msg(net_msg)
    if ret == 0 then
        -- 发送成功
        local flag = get_send_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 : %d ###################\n", net_msg:getPackId());
        end
    elseif ret == 2 then
        -- 表示发送缓存区已满,若不是玩家,则需要缓存,若是玩家直接关闭该连接
        if self:is_user() then
            trace("玩家 socket 发送缓存区已满,断开该连接。\n");
            set_timer(10, self.connection_lost, self);
            write_log(string.format("Error: socket 发送缓存区已满,断开该连接。玩家(%s),send_raw_message\n", self:query("rid")));
        end
    end
    del_message(net_msg)
end

-- 设置该 agent 是否通过验证
function AGENT_TDCLS:set_authed(flag)
    --trace("_________AGENT_TDCLS:set_authed(flag)____%o", flag)
    self.authed = flag;

    if flag then
        -- 该 agent 通过验证,则需要删除析构的定时器
        if is_int(self.timer_id) and self.timer_id > 0 then
            delete_timer(self.timer_id);
            self.timer_id = -1;
        end
    end
end

-- 析构agent并写日志
function AGENT_TDCLS:destruct_not_verify()
    destruct_object(self);
end

function AGENT_TDCLS:set_all_port_no(fport_no, port_no)
    self:set_fport_no(fport_no)
    self:set_port_no(port_no)
end

-- 设置连接号与 agent 的绑定关系
function AGENT_TDCLS:set_port_no(port_no)
    if self.fport_no ~= -1 then
        self.port_no = port_no
    else
        -- 之前已存在旧连接,需要关闭旧连接
        if self.port_no ~= -1 then
            -- 取消本对象的端口-对象的映射
            remove_port_agent(self.port_no);

            -- 关闭该连接
            trace("set_port_no agent repeat close_port %d and new port_no is %d", self.port_no, port_no);
            close_fd(self.port_no);
        end

        -- 设置新的连接号
        self.port_no = port_no;

        -- 设置 port_no 与 agent 绑定关系
        if port_no ~= -1 then
            set_port_agent(port_no, self);
        end

        if type(self.authed) ~= "boolean" or not self.authed then
            -- 该 agent 未验证,则设置超时析构
            self.timer_id = set_timer(60000, self.destruct_not_verify, self);
        end
    end

end

-- 判断agent是否有效
function AGENT_TDCLS:is_valid()
    if self.port_no == -1 then
        return false;
    end

    return true;
end

function AGENT_TDCLS:set_client_ip(client_ip)
    self.client_ip = client_ip
end

function AGENT_TDCLS:get_client_ip()
    return self.client_ip
end

function AGENT_TDCLS:set_server_type(type)
    self.server_type = type
    set_type_port(self.server_type, self.fport_no == -1 and self.port_no or self.fport_no)
end

function AGENT_TDCLS:get_server_type()
    return self.server_type
end

function AGENT_TDCLS:is_user()
    return false
end

-- 设置连接号与 agent 的绑定关系
function AGENT_TDCLS:set_fport_no(port_no)
    -- 之前已存在旧连接,需要关闭旧连接
    if self.fport_no ~= -1 then
        -- 取消本对象的端口-对象的映射
        remove_port_agent(self.fport_no);
    end

    -- 设置新的连接号
    self.fport_no = port_no;

    -- 设置 port_no 与 agent 绑定关系
    if port_no ~= -1 then
        set_port_agent(port_no, self);
    end

end

-- 给逻辑服发送消息,网关服调用
function AGENT_TDCLS:send_logic_message(msg, ...)
    local logic_port = get_map_port(self.port_no)
    if logic_port == -1 then
        trace("no logic server for %o", self.port_no)
        return
    end
    local net_msg = pack_message(msg, ...)
    net_msg:set_seq_fd(self.port_no)
    pcall(send_msg_to_port, logic_port, net_msg);
    del_message(net_msg)
end

function AGENT_TDCLS:forward_logic_message(net_msg)
    local logic_port = get_map_port(self.port_no)
    if logic_port == -1 then
        trace("no logic server for %o", self.port_no)
        return
    end
    net_msg:set_seq_fd(self.port_no)
    pcall(forward_to_port, logic_port, net_msg);
end

function AGENT_TDCLS:print_fd_info()
    trace("____AGENT_TDCLS:print_fd_info()____\n self is %o, fport_no is %o, and bit fport is %o port_no is %o", self, self.fport_no, bit32.band(self.fport_no, 0xFFFF), self.port_no)
end