예제 #1
0
        public RpcPackage PackRequest(string proto, SprotoObject request = null, Int64 session = 0, SprotoObject ud = null)
        {
            //Console.WriteLine("PackRequest {0} {1} {2}",proto,request,session);
            SprotoProtocol protocol = this.C2S.GetProtocol(proto);
            UInt16         tag      = protocol.tag;
            SprotoObject   header   = this.NewPackageHeader(this.C2S, tag, session, ud);

            this.writer.Seek(0, SprotoStream.SEEK_BEGIN);            // clear stream
            SprotoStream writer = this.C2S.Encode(header, this.writer);

            if (request != null)
            {
                string expect = protocol.request;
                if (request.type != expect)
                {
                    SprotoHelper.Error("[SprotoRpc.Request] expect '{0}' got '{1}'", expect, request.type);
                }
                writer = this.C2S.Encode(request, writer);
            }
            RpcPackage package = new RpcPackage();

            package.data = this.C2S.Pack(writer.Buffer, 0, writer.Position, out package.size);
            if (session != 0)
            {
                SprotoHelper.Assert(!this.sessions.ContainsKey(session), String.Format("repeat session: {0}", session));
                RpcMessage message = new RpcMessage();
                message.session        = session;
                message.proto          = proto;
                message.request        = request;
                message.tag            = tag;
                this.sessions[session] = message;
            }
            return(package);
        }
예제 #2
0
        private static void _Parse(SprotoMgr sprotomgr, string proto, string filename)
        {
            Lexer lexer = new Lexer(proto, filename);

            while (lexer.tokens.Count > 0)
            {
                Token token = lexer.tokens[0];
                if ("eof" == token.type)
                {
                    break;
                }
                switch (token.type)
                {
                case "word":
                    SprotoProtocol protocol = parse_protocol(lexer, sprotomgr);
                    sprotomgr.AddProtocol(protocol);
                    break;

                case "point":
                    lexer.pop_token();
                    SprotoType type = parse_type(lexer);
                    sprotomgr.AddType(type);
                    break;

                case "space":
                    ignore(lexer, "space");
                    break;

                default:
                    SprotoHelper.Error(lexer.error_pos(token.line, token.column) + "invalid token:<{0},{1}>", token.type, token.val);
                    break;
                }
            }
        }
예제 #3
0
        public SprotoProtocol GetProtocol(UInt16 tag)
        {
            SprotoProtocol protocol = null;

            if (!this.TagProtocols.TryGetValue(tag, out protocol))
            {
                return(null);
            }
            return(protocol);
        }
예제 #4
0
        public SprotoProtocol GetProtocol(string name)
        {
            SprotoProtocol protocol = null;

            if (!this.Protocols.TryGetValue(name, out protocol))
            {
                return(null);
            }
            return(protocol);
        }
예제 #5
0
 public void AddProtocol(SprotoProtocol protocol)
 {
     if (this.Protocols.ContainsKey(protocol.name))
     {
         SprotoHelper.Error("redefined protocol name '{0}' tag is '{1}'", protocol.name, protocol.tag);
     }
     if (this.TagProtocols.ContainsKey(protocol.tag))
     {
         SprotoHelper.Error("redefined protocol tag '{0}' name is '{1}'", protocol.tag, protocol.name);
     }
     this.Protocols.Add(protocol.name, protocol);
     this.TagProtocols.Add(protocol.tag, protocol);
 }
예제 #6
0
        public RpcPackage PackResponse(string proto, SprotoObject response = null, Int64 session = 0, SprotoObject ud = null)
        {
            //Console.WriteLine("PackResponse {0} {1} {2}",proto,response,session);
            SprotoProtocol protocol = this.S2C.GetProtocol(proto);
            SprotoObject   header   = this.NewPackageHeader(this.S2C, 0, session, ud);

            this.writer.Seek(0, SprotoStream.SEEK_BEGIN);            // clear stream
            SprotoStream writer = this.S2C.Encode(header, this.writer);

            if (response != null)
            {
                string expect = protocol.response;
                if (response.type != expect)
                {
                    SprotoHelper.Error("[SprotoRpc.Response] expect '{0}' got '{1}'", expect, response.type);
                }
                writer = this.S2C.Encode(response, writer);
            }
            RpcPackage package = new RpcPackage();

            package.data = this.S2C.Pack(writer.Buffer, 0, writer.Position, out package.size);
            return(package);
        }
예제 #7
0
        // Parser from binary(*.spb)
        private static void _ParseFromBinary(SprotoMgr sprotomgr, byte[] bytes, int length)
        {
            SprotoMgr    meta   = SprotoParser.Parse(meta_proto);
            SprotoStream reader = new SprotoStream();

            reader.Write(bytes, 0, length);
            reader.Seek(0, SprotoStream.SEEK_BEGIN);
            SprotoObject        group     = meta.Decode("group", reader);
            List <SprotoObject> types     = null;
            List <SprotoObject> protocols = null;

            if (group.Get("type") != null)
            {
                types = group.Get("type");
                foreach (SprotoObject meta_type in types)
                {
                    SprotoType type = new SprotoType();
                    type.name = meta_type["name"];
                    if (meta_type.Has("fields"))
                    {
                        List <SprotoObject> fields = meta_type["fields"];
                        foreach (SprotoObject meta_field in fields)
                        {
                            SprotoField field = new SprotoField();
                            field.name     = meta_field["name"];
                            field.tag      = (UInt16)meta_field["tag"];
                            field.is_array = false;
                            if (meta_field.Has("array"))
                            {
                                field.is_array = (bool)meta_field["array"];
                            }
                            Int64 type_id;
                            if (meta_field.Has("buildin"))
                            {
                                type_id    = meta_field["buildin"];
                                field.type = SprotoParser.BuildInTypeId2Name[type_id];
                                if (type_id == 0 && meta_field.Has("type"))
                                {
                                    // fixed float
                                    field.digit = (UInt16)meta_field["type"];
                                }
                                else if (type_id == 2 && meta_field.Has("type"))
                                {
                                    // binary
                                    field.type = "binary";
                                }
                            }
                            else
                            {
                                type_id = meta_field["type"];
                                SprotoObject t = types[(int)type_id];
                                field.type = t["name"];
                                // map
                                if (meta_field.Has("key"))
                                {
                                    SprotoHelper.Assert(field.is_array);
                                    UInt16 map_index             = (UInt16)meta_field["key"];
                                    List <SprotoObject> t_fields = t["fields"];
                                    string name = null;
                                    foreach (SprotoObject f in t_fields)
                                    {
                                        if (f["tag"] == map_index)
                                        {
                                            name = f["name"];
                                            break;
                                        }
                                    }
                                    SprotoHelper.Assert(name != null, String.Format("map index {0} cann't find in type '{1}'", map_index, field.type));
                                    field.key = name;
                                }
                            }
                            type.AddField(field);
                        }
                    }
                    sprotomgr.AddType(type);
                }
            }
            if (group.Get("protocol") != null)
            {
                protocols = group.Get("protocol");
                foreach (SprotoObject meta_protocol in protocols)
                {
                    SprotoProtocol protocol = new SprotoProtocol();
                    protocol.name = meta_protocol["name"];
                    protocol.tag  = (UInt16)meta_protocol["tag"];
                    if (meta_protocol["request"] != null)
                    {
                        Int64 request = meta_protocol["request"];
                        protocol.request = types[(int)request]["name"];
                    }
                    if (meta_protocol["response"] != null)
                    {
                        Int64 response = meta_protocol["response"];
                        protocol.response = types[(int)response]["name"];
                    }
                    bool confirm = meta_protocol["confirm"];
                    if (confirm)
                    {
                        protocol.response = null;
                    }
                    sprotomgr.AddProtocol(protocol);
                }
            }
        }
예제 #8
0
        private static SprotoProtocol parse_protocol(Lexer lexer, SprotoMgr sprotomgr)
        {
            SprotoProtocol protocol = new SprotoProtocol();
            Token          token    = expect(lexer, "word", "space");

            protocol.name = token.val;
            // keep same behavior with cloudwu's sproto
            // allow { follow by protocol's tag, eg: protocol tag{
            token = expect(lexer, "tag");
            ignore(lexer, "space");
            protocol.tag = Convert.ToUInt16(token.val);
            if (protocol.tag >= SprotoParser.MAX_FIELD_TAG)
            {
                SprotoHelper.Error(lexer.error_pos(token.line, token.column) + "{0} protocol's tag {1} >= {2}", protocol.name, protocol.tag, SprotoParser.MAX_FIELD_TAG);
            }

            expect(lexer, "block_start");
            ignore(lexer, "space");
            while (true)
            {
                token = lexer.tokens[0];
                if ("eof" == token.type || "block_end" == token.type)
                {
                    break;
                }
                token = expect(lexer, "word", "space");
                if (token.val == "request" || token.val == "response")
                {
                    string subprotocol_type = null;
                    Token  token2           = expect(lexer, "word|block_start", "space");
                    if (token2.type == "word")
                    {
                        if (token2.val != "nil")
                        {
                            subprotocol_type = token2.val;
                        }
                    }
                    else
                    {
                        SprotoType typedef = new SprotoType();
                        typedef.name = String.Format("{0}.{1}", protocol.name, token.val);
                        _parse_type(lexer, typedef);
                        sprotomgr.AddType(typedef);
                        subprotocol_type = typedef.name;
                    }
                    if (subprotocol_type != null)
                    {
                        if (token.val == "request")
                        {
                            protocol.request = subprotocol_type;
                        }
                        else
                        {
                            protocol.response = subprotocol_type;
                        }
                    }
                }
                else
                {
                    SprotoHelper.Error(lexer.error_pos(token.line, token.column) + "{0}: invalid subprotocol:{1}", protocol.name, token.val);
                }
            }
            expect(lexer, "block_end");
            if (lexer.tokens[0].type != "eof")
            {
                ignore(lexer, "space");
            }

            string nameReq = $"{protocol.name}.request";

            if (sprotomgr.GetType(nameReq) == null)
            {
                SprotoType typedef = new SprotoType {
                    name = nameReq
                };
                sprotomgr.AddType(typedef);
                protocol.request = nameReq;
            }

            string nameRes = $"{protocol.name}.response";

            if (sprotomgr.GetType(nameRes) == null)
            {
                SprotoType typedef = new SprotoType {
                    name = nameRes
                };
                sprotomgr.AddType(typedef);
                protocol.response = nameRes;
            }

            return(protocol);
        }
예제 #9
0
        public RpcMessage UnpackMessage(byte[] bytes, int size)
        {
            RpcMessage message  = null;
            int        bin_size = 0;

            byte[] bin = this.S2C.Unpack(bytes, 0, size, out bin_size);
            this.reader.Seek(0, SprotoStream.SEEK_BEGIN);            // clear stream
            this.reader.Buffer = bin;

            SprotoObject header = this.S2C.Decode(this.package, this.reader);

            if (header["type"] != null)
            {
                // request
                UInt16         tag      = (UInt16)header["type"];
                SprotoProtocol protocol = this.S2C.GetProtocol(tag);
                SprotoObject   request  = null;
                if (protocol.request != null)
                {
                    request = this.S2C.Decode(protocol.request, this.reader);
                }

                message      = new RpcMessage();
                message.type = "request";
                if (header["session"] != null)
                {
                    message.session = header["session"];
                }
                if (header["ud"] != null)
                {
                    message.ud = header["ud"];
                }
                message.proto = protocol.name;
                message.tag   = protocol.tag;

                message.request = request;
            }
            else
            {
                // response
                SprotoHelper.Assert(header["session"] != null, "session not found");
                Int64 session = header["session"];
                if (this.sessions.TryGetValue(session, out message))
                {
                    //Console.WriteLine("remove session {0}",session);
                    this.sessions.Remove(session);
                }
                SprotoHelper.Assert(message != null, "unknow session");
                message.type = "response";
                if (header["ud"] != null)
                {
                    message.ud = header["ud"];
                }
                SprotoProtocol protocol = this.C2S.GetProtocol(message.tag);
                if (protocol.response != null)
                {
                    SprotoObject response = this.C2S.Decode(protocol.response, this.reader);
                    message.response = response;
                }
            }
            return(message);
        }