Skip to content

Commit

Permalink
support empty request
Browse files Browse the repository at this point in the history
  • Loading branch information
cloudwu committed Sep 7, 2014
1 parent ddf2dec commit f3b7887
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 46 deletions.
29 changes: 17 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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")
```
Expand All @@ -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")
```
Expand Down
10 changes: 6 additions & 4 deletions lsproto.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
11 changes: 7 additions & 4 deletions sproto.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;i<fn;i++) {
int tag = 0;
for (i=0;i<fn;i++,tag++) {
int value = toword(stream + SIZEOF_FIELD * i);
if (value & 1)
return NULL;
if (value & 1) {
tag += (value-1)/2;
continue;
}
value = value/2 - 1;
switch (i) {
case 0: // name
Expand Down Expand Up @@ -362,7 +365,7 @@ import_protocol(struct sproto *s, struct protocol *p, const uint8_t * stream) {
}
}

if (p->name == NULL || p->tag<0 || p->p[SPROTO_REQUEST] == NULL) {
if (p->name == NULL || p->tag<0) {
return NULL;
}

Expand Down
16 changes: 12 additions & 4 deletions sproto.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
47 changes: 26 additions & 21 deletions sprotoparser.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
35 changes: 34 additions & 1 deletion testrpc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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)


0 comments on commit f3b7887

Please sign in to comment.