local skynet = require "skynet" local lfs = require "lfs" local HANDLE_PROTO local root = {} -- 解析协议名字 local function l_get_cmd(name) local pos = string.find(name, "_", 1, true) if not pos then return nil end local protoKey = string.sub(name, 1, pos - 1) local protoName = string.sub(name, pos + 1, #name) return protoKey, protoName end -- 获取rpc文件 local function l_get_rpc(protoKey) local fileName = "rpc_" .. protoKey local fullName = "rpc." .. fileName return fileName, require(fullName) end -- 处理协议 function root.handle_proto(protoName, uid, args) -- 解析出协议名字 local index = string.find(protoName, "%.") protoName = string.sub(protoName, index + 1, string.len(protoName)) -- 名字格式不对 local protoKey, funcName = l_get_cmd(protoName) if not protoKey or not funcName then skynet.error(string.format("handle proto:%s fail", protoName)) return end -- 根据proto_key获取对应的rpc文件 local fileName, rpcFile = l_get_rpc(protoKey) if not rpcFile then skynet.error(string.format("get rpc file:%s fail, protoName:%s", "rpc_" .. protoKey, protoName)) return end -- 执行函数 local func = rpcFile[funcName] if not func then skynet.error(string.format("rpcFile:%s have no func:%s", fileName, funcName)) return end local ok, rs = xpcall( func, function() skynet.error(debug.traceback()) end, uid, args ) if not ok then skynet.error(string.format("rpcFile:%s, do func:%s, args:%s fail", fileName, funcName, tostring(args))) return end return rs end -- 获取http服的协议 function root.get_http_protos() local ret = {} local pb_path = "./proto/pb/" for file in lfs.dir(pb_path) do if string.find(file, "http") or file == "msg.pb" then table.insert(ret, file) end end return pb_path, ret end -- 获取game服的协议 function root.get_game_protos() local list = {} local path = "./proto/pb/" for file in lfs.dir(path) do if not (file == "." or file == "..") then if not string.find(file, "http") then table.insert(list, file) end end end return path, list end -- 初始化协议句柄 function root.init_proto_handle() local ok, handle = pcall(skynet.call, ".proto_mgr", "lua", "get_proto_handle") if not ok or not handle then skynet.error("解析获取协议服务失败...") return false end HANDLE_PROTO = handle return true end -- 解析protobuf协议 function root.parse_protobuf_data(msg) local ok, body = pcall(skynet.call, HANDLE_PROTO, "lua", "decode", "msg.proto_msg", msg) if not ok or not body then skynet.error("解析msg协议包失败...") return false end local protoName = body.protoName local proto_data = body.proto_data local session = body.session if not protoName or not proto_data then skynet.error("msg协议包格式不正确...") return false end local ok, args = pcall(skynet.call, HANDLE_PROTO, "lua", "decode", protoName, proto_data) if not ok or not args then skynet.error(string.format("解析协议[%s]失败...", protoName)) return false end local response local rsp_proto_name = string.gsub(protoName, "_req_", "_rsp_", 1) if not rsp_proto_name then skynet.error(string.format("协议[%s]名称不正确, args:%s...", protoName, tostring(args))) return false end local rsp_proto_func = function(name, res) local ok, body = pcall(skynet.call, HANDLE_PROTO, "lua", "encode", name, res) if not ok or not body then skynet.error(string.format("编码回应协议[%s]失败...", name)) return end local ok, new_body = pcall( skynet.call, HANDLE_PROTO, "lua", "encode", "msg.proto_msg", { protoName = name, proto_data = body, session = session, timestamp = os.time() } ) if not ok or not new_body then skynet.error(string.format("编码回应协议[%s][msg]失败...", name)) return end return new_body end response = { rsp_proto_name = rsp_proto_name, rsp_proto_func = rsp_proto_func } return true, protoName, args, response, session end -- 打包推送的消息 function root.pack_push_msg(name, msg) local ok, body = pcall(skynet.call, HANDLE_PROTO, "lua", "encode", name, msg) if not ok or not body then skynet.error(string.format("编码推送协议[%s]失败...", name)) return end local ok, new_body = pcall( skynet.call, HANDLE_PROTO, "lua", "encode", "msg.proto_msg", { protoName = name, proto_data = body, timestamp = os.time() } ) if not ok or not new_body then skynet.error(string.format("编码推送协议[%s][msg]失败...", name)) return end return new_body end -- 打包回应的消息 function root.pack_response_msg(req_proto_name, rsp_proto_data, session) local rsp_proto_name = string.gsub(req_proto_name, "_req_", "_rsp_", 1) if not rsp_proto_name then skynet.error(string.format("请求协议[%s]名称不正确", req_proto_name)) return end local ok, body = pcall(skynet.call, HANDLE_PROTO, "lua", "encode", rsp_proto_name, rsp_proto_data) if not ok or not body then skynet.error(string.format("编码回应协议[%s]失败...", rsp_proto_name)) return end local ok, new_body = pcall( skynet.call, HANDLE_PROTO, "lua", "encode", "msg.proto_msg", { protoName = rsp_proto_name, proto_data = body, session = session, timestamp = os.time() } ) if not ok or not new_body then skynet.error(string.format("编码回应协议[%s][msg]失败...", rsp_proto_name)) return end return new_body end return root