Skip to content

Commit fd7c9fe

Browse files
author
ithewei
committed
Add example protorpc
1 parent 900833f commit fd7c9fe

16 files changed

+709
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ tags
4040
cscope*
4141
.ycm*
4242

43+
# generated
44+
examples/protorpc/generated
45+
4346
# output
4447
*.pid
4548
*.log

Makefile

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,22 @@ jsonrpc_server: prepare
133133
$(RM) examples/jsonrpc/*.o
134134
$(MAKEF) TARGET=$@ SRCDIRS=". base ssl event" SRCS="examples/jsonrpc/jsonrpc_server.c examples/jsonrpc/jsonrpc.c examples/jsonrpc/cJSON.c"
135135

136+
protorpc: protorpc_client protorpc_server
137+
138+
protorpc_protoc:
139+
bash examples/protorpc/proto/protoc.sh
140+
141+
protorpc_client: prepare protorpc_protoc
142+
$(MAKEF) TARGET=$@ SRCDIRS=". base ssl event cpputil evpp examples/protorpc/generated" \
143+
SRCS="examples/protorpc/protorpc_client.cpp examples/protorpc/protorpc.c" \
144+
LIBS="protobuf"
145+
146+
protorpc_server: prepare protorpc_protoc
147+
$(RM) examples/protorpc/*.o
148+
$(MAKEF) TARGET=$@ SRCDIRS=". base ssl event cpputil evpp examples/protorpc/generated" \
149+
SRCS="examples/protorpc/protorpc_server.cpp examples/protorpc/protorpc.c" \
150+
LIBS="protobuf"
151+
136152
unittest: prepare
137153
$(CC) -g -Wall -O0 -std=c99 -I. -Ibase -o bin/mkdir_p unittest/mkdir_test.c base/hbase.c
138154
$(CC) -g -Wall -O0 -std=c99 -I. -Ibase -o bin/rmdir_p unittest/rmdir_test.c base/hbase.c

README-CN.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ ab -c 100 -n 100000 http://127.0.0.1:8080/
251251
- HTTP客户端: [examples/http_client_test.cpp](examples/http_client_test.cpp)
252252
- WebSocket服务端: [examples/websocket_server_test.cpp](examples/websocket_server_test.cpp)
253253
- WebSocket客户端: [examples/websocket_client_test.cpp](examples/websocket_client_test.cpp)
254+
- protobufRPC示例: [examples/protorpc](examples/protorpc)
254255

255256
### 模拟实现著名的命令行工具
256257
- 网络连接工具: [examples/nc](examples/nc.c)

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ ab -c 100 -n 100000 http://127.0.0.1:8080/
248248
- [examples/http_client_test.cpp](examples/http_client_test.cpp)
249249
- [examples/websocket_server_test.cpp](examples/websocket_server_test.cpp)
250250
- [examples/websocket_client_test.cpp](examples/websocket_client_test.cpp)
251+
- [examples/protorpc](examples/protorpc)
251252

252253
### simulate well-known command line tools
253254
- [examples/nc](examples/nc.c)

examples/protorpc/handler/calc.h

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#ifndef HV_PROTO_RPC_HANDLER_CALC_H_
2+
#define HV_PROTO_RPC_HANDLER_CALC_H_
3+
4+
#include "../router.h"
5+
6+
#include "../generated/calc.pb.h"
7+
8+
void calc_add(const protorpc::Request& req, protorpc::Response* res) {
9+
// params
10+
if (req.params_size() != 2) {
11+
return bad_request(req, res);
12+
}
13+
protorpc::CalcParam param1, param2;
14+
if (!param1.ParseFromString(req.params(0)) ||
15+
!param2.ParseFromString(req.params(1))) {
16+
return bad_request(req, res);
17+
}
18+
19+
// result
20+
protorpc::CalcResult result;
21+
result.set_num(param1.num() + param2.num());
22+
res->set_result(result.SerializeAsString());
23+
}
24+
25+
void calc_sub(const protorpc::Request& req, protorpc::Response* res) {
26+
// params
27+
if (req.params_size() != 2) {
28+
return bad_request(req, res);
29+
}
30+
protorpc::CalcParam param1, param2;
31+
if (!param1.ParseFromString(req.params(0)) ||
32+
!param2.ParseFromString(req.params(1))) {
33+
return bad_request(req, res);
34+
}
35+
36+
// result
37+
protorpc::CalcResult result;
38+
result.set_num(param1.num() - param2.num());
39+
res->set_result(result.SerializeAsString());
40+
}
41+
42+
void calc_mul(const protorpc::Request& req, protorpc::Response* res) {
43+
// params
44+
if (req.params_size() != 2) {
45+
return bad_request(req, res);
46+
}
47+
protorpc::CalcParam param1, param2;
48+
if (!param1.ParseFromString(req.params(0)) ||
49+
!param2.ParseFromString(req.params(1))) {
50+
return bad_request(req, res);
51+
}
52+
53+
// result
54+
protorpc::CalcResult result;
55+
result.set_num(param1.num() * param2.num());
56+
res->set_result(result.SerializeAsString());
57+
}
58+
59+
void calc_div(const protorpc::Request& req, protorpc::Response* res) {
60+
// params
61+
if (req.params_size() != 2) {
62+
return bad_request(req, res);
63+
}
64+
protorpc::CalcParam param1, param2;
65+
if (!param1.ParseFromString(req.params(0)) ||
66+
!param2.ParseFromString(req.params(1))) {
67+
return bad_request(req, res);
68+
}
69+
if (param2.num() == 0) {
70+
return bad_request(req, res);
71+
}
72+
73+
// result
74+
protorpc::CalcResult result;
75+
result.set_num(param1.num() / param2.num());
76+
res->set_result(result.SerializeAsString());
77+
}
78+
79+
#endif // HV_PROTO_RPC_HANDLER_CALC_H_

examples/protorpc/handler/handler.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#ifndef HV_PROTO_RPC_HANDLER_H_
2+
#define HV_PROTO_RPC_HANDLER_H_
3+
4+
#include "../router.h"
5+
6+
void error_response(protorpc::Response* res, int code, const std::string& message) {
7+
res->mutable_error()->set_code(code);
8+
res->mutable_error()->set_message(message);
9+
}
10+
11+
void not_found(const protorpc::Request& req, protorpc::Response* res) {
12+
error_response(res, 404, "Not Found");
13+
}
14+
15+
void bad_request(const protorpc::Request& req, protorpc::Response* res) {
16+
error_response(res, 400, "Bad Request");
17+
}
18+
19+
#endif // HV_PROTO_RPC_HANDLER_H_

examples/protorpc/handler/login.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#ifndef HV_PROTO_RPC_HANDLER_LOGIN_H_
2+
#define HV_PROTO_RPC_HANDLER_LOGIN_H_
3+
4+
#include "../router.h"
5+
6+
#include "../generated/login.pb.h"
7+
8+
void login(const protorpc::Request& req, protorpc::Response* res) {
9+
// params
10+
if (req.params_size() == 0) {
11+
return bad_request(req, res);
12+
}
13+
protorpc::LoginParam param;
14+
if (!param.ParseFromString(req.params(0))) {
15+
return bad_request(req, res);
16+
}
17+
18+
// result
19+
protorpc::LoginResult result;
20+
result.set_user_id(123456);
21+
result.set_token(param.username() + ":" + param.password());
22+
res->set_result(result.SerializeAsString());
23+
}
24+
25+
#endif // HV_PROTO_RPC_HANDLER_LOGIN_H_

examples/protorpc/proto/base.proto

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
syntax = "proto3";
2+
3+
package protorpc;
4+
5+
message Error {
6+
int32 code = 1;
7+
string message = 2;
8+
}
9+
10+
message Request {
11+
uint64 id = 1;
12+
string method = 2;
13+
repeated bytes params = 3;
14+
}
15+
16+
message Response {
17+
uint64 id = 1;
18+
optional bytes result = 2;
19+
optional Error error = 3;
20+
}

examples/protorpc/proto/calc.proto

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
syntax = "proto3";
2+
3+
package protorpc;
4+
5+
message CalcParam {
6+
int64 num = 1;
7+
}
8+
9+
message CalcResult {
10+
int64 num = 1;
11+
}

examples/protorpc/proto/login.proto

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
syntax = "proto3";
2+
3+
package protorpc;
4+
5+
message LoginParam {
6+
string username = 1;
7+
string password = 2;
8+
}
9+
10+
message LoginResult {
11+
uint64 user_id = 1;
12+
string token = 2;
13+
}

examples/protorpc/proto/protoc.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/bash
2+
3+
cd `dirname $0`
4+
5+
PROTOC=`which protoc`
6+
if [ $? -ne 0 ]; then
7+
echo "Not found command protoc!"
8+
echo "Please install libprotobuf first!"
9+
exit 1
10+
fi
11+
12+
CPP_OUT_DIR=../generated
13+
if [ ! -d "${CPP_OUT_DIR}" ]; then
14+
mkdir -p ${CPP_OUT_DIR}
15+
fi
16+
17+
set -x
18+
${PROTOC} --cpp_out=${CPP_OUT_DIR} *.proto

examples/protorpc/protorpc.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#include "protorpc.h"
2+
3+
#include <string.h> // import memcpy
4+
5+
int protorpc_pack(const protorpc_message* msg, void* buf, int len) {
6+
if (!msg || !buf || !len) return -1;
7+
const protorpc_head* head = &(msg->head);
8+
unsigned int packlen = protorpc_package_length(head);
9+
// Check is buffer enough
10+
if (len < packlen) {
11+
return -2;
12+
}
13+
unsigned char* p = (unsigned char*)buf;
14+
// flags
15+
*p++ = head->flags;
16+
// hton length
17+
unsigned int length = head->length;
18+
*p++ = (length >> 24) & 0xFF;
19+
*p++ = (length >> 16) & 0xFF;
20+
*p++ = (length >> 8) & 0xFF;
21+
*p++ = length & 0xFF;
22+
// memcpy body
23+
if (msg->body && head->length) {
24+
memcpy(p, msg->body, head->length);
25+
}
26+
27+
return packlen;
28+
}
29+
30+
int protorpc_unpack(protorpc_message* msg, const void* buf, int len) {
31+
if (!msg || !buf || !len) return -1;
32+
if (len < PROTORPC_HEAD_LENGTH) return -2;
33+
protorpc_head* head = &(msg->head);
34+
const unsigned char* p = (const unsigned char*)buf;
35+
// flags
36+
head->flags = *p++;
37+
// ntoh length
38+
head->length = ((unsigned int)*p++) << 24;
39+
head->length |= ((unsigned int)*p++) << 16;
40+
head->length |= ((unsigned int)*p++) << 8;
41+
head->length |= *p++;
42+
// Check is buffer enough
43+
unsigned int packlen = protorpc_package_length(head);
44+
if (len < packlen) {
45+
return -3;
46+
}
47+
// NOTE: just shadow copy
48+
if (len > PROTORPC_HEAD_LENGTH) {
49+
msg->body = (const char*)buf + PROTORPC_HEAD_LENGTH;
50+
}
51+
52+
return packlen;
53+
}

examples/protorpc/protorpc.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#ifndef HV_PROTO_RPC_H_
2+
#define HV_PROTO_RPC_H_
3+
4+
#ifdef __cplusplus
5+
extern "C" {
6+
#endif
7+
8+
// flags:1byte + length:4bytes = 5bytes
9+
#define PROTORPC_HEAD_LENGTH 5
10+
typedef struct {
11+
unsigned char flags;
12+
unsigned int length;
13+
} protorpc_head;
14+
15+
typedef const char* protorpc_body;
16+
17+
typedef struct {
18+
protorpc_head head;
19+
protorpc_body body;
20+
} protorpc_message;
21+
22+
static inline unsigned int protorpc_package_length(const protorpc_head* head) {
23+
return PROTORPC_HEAD_LENGTH + head->length;
24+
}
25+
26+
// @retval >0 package_length, <0 error
27+
int protorpc_pack(const protorpc_message* msg, void* buf, int len);
28+
// @retval >0 package_length, <0 error
29+
int protorpc_unpack(protorpc_message* msg, const void* buf, int len);
30+
31+
#ifdef __cplusplus
32+
} // extern "C"
33+
#endif
34+
35+
#endif // HV_PROTO_RPC_H_

0 commit comments

Comments
 (0)