RPCServer.lua 4.2 KB
Newer Older
baidwwy's avatar
lua  
baidwwy 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
-- @Author       : GGELUA
-- @Date         : 2021-09-17 08:26:43
-- @Last Modified by: baidwwy
-- @Last Modified time: 2021-12-08 12:04:37

local adler32 = require('zlib').adler32
local m_pack = require('cmsgpack').pack
local m_unpack = require('cmsgpack.safe').unpack

local c_isyieldable = coroutine.isyieldable
local c_runing = coroutine.running
local c_yield = coroutine.yield
local c_resume = coroutine.resume
local c_create = coroutine.create
local t_unpack = table.unpack

local PackServer = require('HPSocket.PackServer')
local RPCServer = class('RPCServer', PackServer)

local _REG = setmetatable({}, {__mode = 'k'}) --接收函数
local _CBK = setmetatable({}, {__mode = 'k'}) --等待返回的协程
local _PAS = setmetatable({}, {__mode = 'k'}) --验证连接

function RPCServer:RPCServer()
    PackServer.PackServer(self) --初始化父类
    local reg = {}
    _REG[self] = reg --private
    _CBK[self] = {} --private
    _PAS[self] = {}
    return setmetatable(
        {},
        {
            __newindex = function(t, k, v)
                if type(v) == 'function' then
                    reg[k] = v
                    reg[adler32(k)] = v
                end
            end,
            __index = reg
        }
    )
end

function RPCServer:__index(k) --调用方法
    local co, main = c_runing()
    local funp = type(k) == 'string' and adler32(k) or k
    if co and not main and c_isyieldable() then --如果有协程,则有返回值
        return function(self, id, ...)
            if id then
                local cop = adler32(tostring(co))
                _CBK[self][cop] = co
                self._hp:Send(id, m_pack {funp, cop, ...})
                return c_yield()
            end
        end
    end
    return function(self, id, ...)
        if id then
            self._hp:Send(id, m_pack {funp, 0, ...})
        end
    end
end

function RPCServer:发送(id, ...)
    return self._hp:Send(id, m_pack {...})
end

function RPCServer:_连接事件(id, ip, port)
    _PAS[self][id] = true
    if self.连接事件 then
        local r = ggexpcall(self.连接事件, self, id, ip, port)
        _PAS[self][id] = r ~= false
    end
end

local function cofunc(self, id, cop, func, ...)
    self._hp:Send(id, m_pack {0, cop, func(self, id, ...)})
end

function RPCServer:_接收事件(id, data)
    if rawget(self, '接收事件') then
        self:接收事件(id, data)
        return
    end

    local t = m_unpack(data)
    if type(t) ~= 'table' then
        return
    end

    if _PAS[self][id] then
        local funp, cop = t[1], t[2]
        if funp == 0 then --返回
            local co = _CBK[self][cop]
            if co then
                _CBK[self][cop] = nil
                coroutine.xpcall(co, t_unpack(t, 3))
            end
        else
            local func = _REG[self][funp]
            if func then
                if cop == 0 then --没有返回
                    func(self, id, t_unpack(t, 3))
                else
                    local r = coroutine.xpcall(cofunc, self, id, cop, func, t_unpack(t, 3))
                    if r == coroutine.FALSE then
                        self._hp:Send(id, m_pack {0, cop, nil})
                    end
                end
            elseif rawget(self, 'RPC事件') then --未注册的函数
                func = self.RPC事件
                if cop == 0 then --没有返回
                    func(self, id, funp, t_unpack(t, 3))
                else
                    local r = coroutine.xpcall(cofunc, self, id, cop, func, funp, t_unpack(t, 3))
                    if r == coroutine.FALSE then
                        self._hp:Send(id, m_pack {0, cop, nil})
                    end
                end
            elseif cop ~= 0 then
                self._hp:Send(id, m_pack {0, cop, nil})
            end
        end
    elseif rawget(self, '验证事件') then
        local funp, cop = t[1], t[2]
        if funp == 261030967 then --adler32('验证')
            local r = self:验证事件(id, t_unpack(t, 3))
            self._hp:Send(id, m_pack {0, cop, r})
            if r then
                _PAS[self][id] = true
            else
                self:断开(id)
            end
        end
    end
end

return RPCServer