diff --git a/README.md b/README.md index b6afeca..7f84b49 100644 --- a/README.md +++ b/README.md @@ -210,8 +210,12 @@ All the fields must be encoded in ascending order (by tag). The tags of fields c The header is a 16bit integer. It is the number of fields. -Each field in field part is two 16bit integer. The first one is the tag increment. The base of tags is 0, if your tags in message in continuous, the tag increment will be zero. -the second one indicates the value of this field. If it is 0, the real value is encoded in data part, or minus 1 as the field value. +Each field in field part is a 16bit integer (n). If n is zero, that means the field data is encoded in data part ; + +If n is even (and not zero), the value of this field is n/2-1 ; + +If n is odd, that means the tags is not continuous, and we should add current tag by (n+1)/2 . + Read the examples below to see more details. Notice: If the tag is not declared in schema, the decoder will simply ignore the field for protocol version compatibility. @@ -222,9 +226,9 @@ Example 1: person { name = "Alice" , age = 13, marital = false } 03 00 (fn = 3) -00 00 00 00 (id = 0, value in data part) -00 00 0E 00 (id = 1, value = 13) -00 00 01 00 (id = 2, value = false) +00 00 (id = 0, value in data part) +1C 00 (id = 1, value = 13) +02 00 (id = 2, value = false) 05 00 00 00 (sizeof "Alice") 41 6C 69 63 65 ("Alice") ``` @@ -241,18 +245,19 @@ person { } 04 00 (fn = 4) -00 00 00 00 (id = 0, value in data part) -00 00 29 00 (id = 1, value = 40) -01 00 00 00 (id = 3 / skip id 2, value in data part) +00 00 (id = 0, value in data part) +52 00 (id = 1, value = 40) +01 00 (skip id = 2) +00 00 (id = 3, value in data part) 03 00 00 00 (sizeof "Bob") 42 6F 62 ("Bob") -17 00 00 00 (sizeof struct) +11 00 00 00 (sizeof struct) 03 00 (fn = 3) -00 00 00 00 (id = 0, ref = 0) -00 00 0E 00 (id = 1, value = 13) -00 00 01 00 (id = 2, value = false) +00 00 (id = 0, value in data part) +1C 00 (id = 1, value = 13) +02 00 (id = 2, value = false) 05 00 00 00 (sizeof "Alice") 41 6C 69 63 65 ("Alice") ``` diff --git a/lsproto.c b/lsproto.c index c2ef29e..602f86e 100644 --- a/lsproto.c +++ b/lsproto.c @@ -422,14 +422,16 @@ lprotocol(lua_State *L) { } struct sproto_type * request = sproto_protoquery(sp, tag, SPROTO_REQUEST); if (request == NULL) { - return 0; + lua_pushnil(L); + } else { + lua_pushlightuserdata(L, request); } - lua_pushlightuserdata(L, request); struct sproto_type * response = sproto_protoquery(sp, tag, SPROTO_RESPONSE); if (response == NULL) { - return 2; + lua_pushnil(L); + } else { + lua_pushlightuserdata(L, response); } - lua_pushlightuserdata(L, response); return 3; } diff --git a/sproto.c b/sproto.c index c701d09..0f519d1 100644 --- a/sproto.c +++ b/sproto.c @@ -329,10 +329,13 @@ import_protocol(struct sproto *s, struct protocol *p, const uint8_t * stream) { p->p[SPROTO_REQUEST] = NULL; p->p[SPROTO_RESPONSE] = NULL; int i; - for (i=0;iname == NULL || p->tag<0 || p->p[SPROTO_REQUEST] == NULL) { + if (p->name == NULL || p->tag<0) { return NULL; } diff --git a/sproto.lua b/sproto.lua index 423a561..a6180b0 100644 --- a/sproto.lua +++ b/sproto.lua @@ -126,11 +126,19 @@ function rpc:dispatch(...) if header.type then -- request local proto = queryproto(self.__proto, header.type) - local result = core.decode(proto.request, content) - if header_tmp.session then - return "REQUEST", proto.name, result, gen_response(self, proto.response, header_tmp.session) + if proto.request then + local result = core.decode(proto.request, content) + if header_tmp.session then + return "REQUEST", proto.name, result, gen_response(self, proto.response, header_tmp.session) + else + return "REQUEST", proto.name, result + end else - return "REQUEST", proto.name, result + if header_tmp.session then + return "REQUEST", proto.name, nil, gen_response(self, proto.response, header_tmp.session) + else + return "REQUEST", proto.name + end end else -- response diff --git a/sprotoparser.lua b/sprotoparser.lua index 1b9dcfc..f6b2439 100644 --- a/sprotoparser.lua +++ b/sprotoparser.lua @@ -271,30 +271,35 @@ local function packtype(name, t, alltypes) end local function packproto(name, p, alltypes) - if p.request == nil then - error(string.format("Protocol %s need request", name)) - end - local request = alltypes[p.request] - if request == nil then - error(string.format("Protocol %s request type %s not found", name, p.request)) +-- if p.request == nil then +-- error(string.format("Protocol %s need request", name)) +-- end + if p.request then + local request = alltypes[p.request] + if request == nil then + error(string.format("Protocol %s request type %s not found", name, p.request)) + end end - local tmp - if p.response then - tmp = { - "\4\0", -- 4 fields - "\0\0", -- name (id=0, ref=0) - packvalue(p.tag), -- tag (tag=1) - packvalue(alltypes[p.request]), -- request typename (tag=2) - packvalue(alltypes[p.response]), -- response typename (tag=3) - } + local tmp = { + "\4\0", -- 4 fields + "\0\0", -- name (id=0, ref=0) + packvalue(p.tag), -- tag (tag=1) + } + if p.request == nil and p.response == nil then + tmp[1] = "\2\0" else - tmp = { - "\3\0", -- 3 fields - "\0\0", -- name (id=0, ref=0) - packvalue(p.tag), -- tag (tag=1) - packvalue(alltypes[p.request]), -- request typename (tag=2) - } + if p.request then + table.insert(tmp, packvalue(alltypes[p.request])) -- request typename (tag=2) + else + table.insert(tmp, "\1\0") + end + if p.response then + table.insert(tmp, packvalue(alltypes[p.response])) -- request typename (tag=3) + else + tmp[1] = "\3\0" + end end + table.insert(tmp, packbytes(name)) return packbytes(table.concat(tmp)) diff --git a/testrpc.lua b/testrpc.lua index 55f95d7..7f123a9 100644 --- a/testrpc.lua +++ b/testrpc.lua @@ -15,6 +15,18 @@ foobar 1 { ok 0 : boolean } } + +foo 2 { + response { + ok 0 : boolean + } +} + +bar 3 {} + +blackhole 4 { + request {} +} ]] -- The type package must has two field : type and session @@ -23,7 +35,7 @@ local client = sp:rpc "package" print("client request foobar") local req = client:request("foobar", { what = "foo" }, 1) -print("request package size =", #req) +print("request foobar size =", #req) local type, name, request, response = server:dispatch(req) assert(type == "REQUEST" and name == "foobar") print_r(request) @@ -34,3 +46,24 @@ print("client dispatch") local type, session, response = client:dispatch(resp) assert(type == "RESPONSE" and session == 1) print_r(response) + +local req = client:request("foo", nil, 2) +print("request foo size =", #req) +local type, name, request, response = server:dispatch(req) +assert(type == "REQUEST" and name == "foo" and request == nil) +local resp = response { ok = false } +print("response package size =", #resp) +print("client dispatch") +local type, session, response = client:dispatch(resp) +assert(type == "RESPONSE" and session == 2) +print_r(response) + +local req = client:request("bar") -- bar has no response +print("request bar size =", #req) +local type, name, request, response = server:dispatch(req) +assert(type == "REQUEST" and name == "bar" and request == nil and response == nil) + +local req = client:request "blackhole" +print("request blackhole size = ", #req) + +