Skip to content

Commit 64c102b

Browse files
committed
samples: modules: thrift: add samples for thrift module
Here we add a client and server samples for the basic "hello" service. These samples are designed to be run by either Zephyr or the host machine, interchangeably. Additionally, there is a python version of the client to demonstrate Thrift's cross-language capabilities. This code was merged from the following repository at the commit specified below, with minor formatting and coding-style modifications. https://github.com/zephyrproject-rtos/gsoc-2022-thrift e12e014d295918cc5ba0b4c507d1bf595a2f539a Signed-off-by: Chris Friedt <[email protected]>
1 parent 9fc1cc7 commit 64c102b

21 files changed

+1037
-0
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Copyright 2022 Meta
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
cmake_minimum_required(VERSION 3.20.0)
5+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
6+
project(thrift_hello_server)
7+
8+
FILE(GLOB app_sources
9+
src/*.cpp
10+
)
11+
12+
include(${ZEPHYR_BASE}/modules/thrift/cmake/thrift.cmake)
13+
14+
set(generated_sources "")
15+
set(gen_dir ${ZEPHYR_BINARY_DIR}/misc/generated/thrift_hello)
16+
list(APPEND generated_sources ${gen_dir}/gen-cpp/hello_types.h)
17+
list(APPEND generated_sources ${gen_dir}/gen-cpp/Hello.cpp)
18+
list(APPEND generated_sources ${gen_dir}/gen-cpp/Hello.h)
19+
list(APPEND app_sources ${generated_sources})
20+
21+
thrift(
22+
app
23+
cpp
24+
:no_skeleton
25+
${gen_dir}
26+
${ZEPHYR_BASE}/samples/modules/thrift/hello/hello.thrift
27+
""
28+
${generated_sources}
29+
)
30+
31+
target_sources(app PRIVATE ${app_sources})
32+
33+
# needed because std::iterator was deprecated with -std=c++17
34+
target_compile_options(app PRIVATE -Wno-deprecated-declarations)
35+
36+
# convert .pem files to array data at build time
37+
zephyr_include_directories(${gen_dir})
38+
39+
generate_inc_file_for_target(
40+
app
41+
${ZEPHYR_BASE}/samples/modules/thrift/hello/qemu-cert.pem
42+
${gen_dir}/qemu_cert.pem.inc
43+
)
44+
45+
generate_inc_file_for_target(
46+
app
47+
${ZEPHYR_BASE}/samples/modules/thrift/hello/qemu-key.pem
48+
${gen_dir}/qemu_key.pem.inc
49+
)
50+
51+
generate_inc_file_for_target(
52+
app
53+
${ZEPHYR_BASE}/samples/modules/thrift/hello/native-cert.pem
54+
${gen_dir}/native_cert.pem.inc
55+
)
56+
57+
generate_inc_file_for_target(
58+
app
59+
${ZEPHYR_BASE}/samples/modules/thrift/hello/native-key.pem
60+
${gen_dir}/native_key.pem.inc
61+
)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
# Copyright (c) 2022 Meta
3+
4+
source "Kconfig.zephyr"
5+
6+
config THRIFT_COMPACT_PROTOCOL
7+
bool "Use TCompactProtocol in samples"
8+
depends on THRIFT
9+
help
10+
Enable this option to use TCompactProtocol in samples
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Copyright 2022 Meta
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
.PHONY: all clean
5+
6+
CXXFLAGS :=
7+
CXXFLAGS += -std=c++17
8+
9+
GEN_DIR = gen-cpp
10+
GENSRC = $(GEN_DIR)/Hello.cpp $(GEN_DIR)/Hello.h $(GEN_DIR)/hello_types.h
11+
GENHDR = $(filter %.h, $(GENSRC))
12+
GENOBJ = $(filter-out %.h, $(GENSRC:.cpp=.o))
13+
14+
THRIFT_FLAGS :=
15+
THRIFT_FLAGS += $(shell pkg-config --cflags thrift)
16+
THRIFT_FLAGS += -I$(GEN_DIR)
17+
THRIFT_LIBS = $(shell pkg-config --libs thrift)
18+
19+
all: hello_client hello_client_compact hello_client_ssl hello_client_py.stamp
20+
21+
hello_client.stamp: ../hello.thrift
22+
thrift --gen cpp:no_skeleton $<
23+
24+
$(GENSRC): hello_client.stamp
25+
touch $@
26+
27+
%.o: %.cpp $(GENHDR)
28+
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(THRIFT_FLAGS) -o $@ -c $<
29+
30+
hello_client: src/main.cpp $(GENOBJ) $(GENHDR)
31+
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(THRIFT_FLAGS) -o $@ $< $(GENOBJ) $(THRIFT_LIBS)
32+
33+
hello_client_compact: src/main.cpp $(GENOBJ) $(GENHDR)
34+
$(CXX) -DCONFIG_THRIFT_COMPACT_PROTOCOL=1 $(CPPFLAGS) $(CXXFLAGS) $(THRIFT_FLAGS) -o $@ $< $(GENOBJ) $(THRIFT_LIBS)
35+
36+
hello_client_ssl: src/main.cpp $(GENOBJ) $(GENHDR)
37+
$(CXX) -DCONFIG_THRIFT_SSL_SOCKET=1 $(CPPFLAGS) $(CXXFLAGS) $(THRIFT_FLAGS) -o $@ $< $(GENOBJ) $(THRIFT_LIBS)
38+
39+
hello_client_py.stamp: ../hello.thrift
40+
thrift --gen py $<
41+
touch $@
42+
43+
clean:
44+
rm -Rf hello_client hello_client_compact hello_client_ssl $(GEN_DIR) gen-py *.stamp
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) 2023, Meta
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
6+
"""Thrift Hello Client Sample
7+
8+
Connect to a hello service and demonstrate the
9+
ping(), echo(), and counter() Thrift RPC methods.
10+
11+
Usage:
12+
./hello_client.py [ip]
13+
"""
14+
15+
import argparse
16+
import sys
17+
sys.path.append('gen-py')
18+
19+
from thrift.protocol import TBinaryProtocol
20+
from thrift.transport import TTransport
21+
from thrift.transport import TSocket
22+
from hello import Hello
23+
24+
25+
def parse_args():
26+
parser = argparse.ArgumentParser(allow_abbrev=False)
27+
parser.add_argument('--ip', default='192.0.2.1',
28+
help='IP address of hello server')
29+
30+
return parser.parse_args()
31+
32+
33+
def main():
34+
args = parse_args()
35+
36+
transport = TSocket.TSocket(args.ip, 4242)
37+
transport = TTransport.TBufferedTransport(transport)
38+
protocol = TBinaryProtocol.TBinaryProtocol(transport)
39+
client = Hello.Client(protocol)
40+
41+
transport.open()
42+
43+
client.ping()
44+
client.echo('Hello, world!')
45+
46+
# necessary to mitigate unused variable warning with for i in range(5)
47+
i = 0
48+
while i < 5:
49+
client.counter()
50+
i = i + 1
51+
52+
transport.close()
53+
54+
55+
if __name__ == '__main__':
56+
main()
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# CONFIG_LIB_CPLUSPLUS Dependencies
2+
CONFIG_NEWLIB_LIBC=y
3+
CONFIG_NEWLIB_LIBC_NANO=n
4+
5+
# CONFIG_THRIFT Dependencies
6+
CONFIG_CPP=y
7+
CONFIG_STD_CPP17=y
8+
CONFIG_CPP_EXCEPTIONS=y
9+
CONFIG_EXTERNAL_LIBCPP=y
10+
CONFIG_POSIX_API=y
11+
CONFIG_NETWORKING=y
12+
CONFIG_NET_SOCKETS=y
13+
CONFIG_NET_SOCKETPAIR=y
14+
CONFIG_HEAP_MEM_POOL_SIZE=16384
15+
CONFIG_EVENTFD=y
16+
17+
CONFIG_THRIFT=y
18+
19+
CONFIG_TEST_RANDOM_GENERATOR=y
20+
# pthread_cond_wait() triggers sentinel for some reason
21+
CONFIG_STACK_SENTINEL=n
22+
23+
# Generic networking options
24+
CONFIG_NETWORKING=y
25+
CONFIG_NET_UDP=y
26+
CONFIG_NET_TCP=y
27+
CONFIG_NET_IPV6=n
28+
CONFIG_NET_IPV4=y
29+
CONFIG_NET_SOCKETS=y
30+
CONFIG_POSIX_MAX_FDS=6
31+
CONFIG_NET_CONNECTION_MANAGER=y
32+
33+
# Kernel options
34+
CONFIG_ENTROPY_GENERATOR=y
35+
CONFIG_TEST_RANDOM_GENERATOR=y
36+
CONFIG_INIT_STACKS=y
37+
38+
# Logging
39+
CONFIG_NET_LOG=y
40+
CONFIG_LOG=y
41+
CONFIG_NET_STATISTICS=y
42+
CONFIG_PRINTK=y
43+
44+
# Network buffers
45+
CONFIG_NET_PKT_RX_COUNT=16
46+
CONFIG_NET_PKT_TX_COUNT=16
47+
CONFIG_NET_BUF_RX_COUNT=64
48+
CONFIG_NET_BUF_TX_COUNT=64
49+
CONFIG_NET_CONTEXT_NET_PKT_POOL=y
50+
51+
# IP address options
52+
CONFIG_NET_MAX_CONTEXTS=10
53+
54+
# Network application options and configuration
55+
CONFIG_NET_CONFIG_SETTINGS=y
56+
CONFIG_NET_CONFIG_NEED_IPV6=n
57+
CONFIG_NET_CONFIG_NEED_IPV4=y
58+
CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1"
59+
CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2"
60+
61+
# Number of socket descriptors might need adjusting
62+
# if there are more than 1 handlers defined.
63+
CONFIG_POSIX_MAX_FDS=16
64+
65+
# Some platforms require relatively large stack sizes.
66+
# This can be tuned per-board.
67+
CONFIG_MAIN_STACK_SIZE=8192
68+
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=8192
69+
CONFIG_NET_TCP_WORKQ_STACK_SIZE=4096
70+
CONFIG_NET_MGMT_EVENT_STACK_SIZE=4096
71+
CONFIG_IDLE_STACK_SIZE=4096
72+
CONFIG_NET_RX_STACK_SIZE=8192
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
sample:
2+
description: Hello Thrift client sample
3+
name: hello thrift client
4+
common:
5+
tags: thrift cpp sample
6+
build_only: true
7+
modules:
8+
- thrift
9+
platform_allow: mps2_an385 qemu_x86_64
10+
tests:
11+
sample.thrift.hello.server.binaryProtocol: {}
12+
sample.thrift.hello.server.compactProtocol:
13+
extra_configs:
14+
- CONFIG_THRIFT_COMPACT_PROTOCOL=y
15+
sample.thrift.hello.server.tlsTransport:
16+
extra_args: OVERLAY_CONFIG="../overlay-tls.conf"
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
* Copyright 2022 Young Mei
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifdef __ZEPHYR__
8+
#include <zephyr/kernel.h>
9+
#endif
10+
11+
#include <cstdlib>
12+
#include <iostream>
13+
14+
#include <fcntl.h>
15+
16+
#include <thrift/protocol/TBinaryProtocol.h>
17+
#include <thrift/protocol/TCompactProtocol.h>
18+
#include <thrift/transport/TBufferTransports.h>
19+
#include <thrift/transport/TSSLSocket.h>
20+
#include <thrift/transport/TSocket.h>
21+
22+
#include "Hello.h"
23+
24+
using namespace apache::thrift;
25+
using namespace apache::thrift::protocol;
26+
using namespace apache::thrift::transport;
27+
28+
#ifndef IS_ENABLED
29+
#define IS_ENABLED(flag) flag
30+
#endif
31+
32+
#ifndef CONFIG_THRIFT_COMPACT_PROTOCOL
33+
#define CONFIG_THRIFT_COMPACT_PROTOCOL 0
34+
#endif
35+
36+
#ifndef CONFIG_THRIFT_SSL_SOCKET
37+
#define CONFIG_THRIFT_SSL_SOCKET 0
38+
#endif
39+
40+
#ifdef __ZEPHYR__
41+
int main(void)
42+
#else
43+
int main(int argc, char **argv)
44+
#endif
45+
{
46+
std::string my_addr;
47+
48+
#ifdef __ZEPHYR__
49+
my_addr = CONFIG_NET_CONFIG_PEER_IPV4_ADDR;
50+
#else
51+
if (IS_ENABLED(CONFIG_THRIFT_SSL_SOCKET)) {
52+
if (argc != 5) {
53+
printf("usage: %s <ip> <native-cert.pem> <native-key.pem> "
54+
"<qemu-cert.pem>\n",
55+
argv[0]);
56+
return EXIT_FAILURE;
57+
}
58+
}
59+
60+
if (argc >= 2) {
61+
my_addr = std::string(argv[1]);
62+
} else {
63+
my_addr = "192.0.2.1";
64+
}
65+
#endif
66+
67+
int port = 4242;
68+
std::shared_ptr<TProtocol> protocol;
69+
std::shared_ptr<TTransport> transport;
70+
std::shared_ptr<TSSLSocketFactory> socketFactory;
71+
std::shared_ptr<TTransport> trans;
72+
73+
if (IS_ENABLED(CONFIG_THRIFT_SSL_SOCKET)) {
74+
const int port = 4242;
75+
socketFactory = std::make_shared<TSSLSocketFactory>();
76+
socketFactory->authenticate(true);
77+
78+
#ifdef __ZEPHYR__
79+
static const char qemu_cert_pem[] = {
80+
#include "qemu_cert.pem.inc"
81+
};
82+
83+
static const char qemu_key_pem[] = {
84+
#include "qemu_key.pem.inc"
85+
};
86+
87+
static const char native_cert_pem[] = {
88+
#include "native_cert.pem.inc"
89+
};
90+
91+
socketFactory->loadCertificateFromBuffer(qemu_cert_pem);
92+
socketFactory->loadPrivateKeyFromBuffer(qemu_key_pem);
93+
socketFactory->loadTrustedCertificatesFromBuffer(native_cert_pem);
94+
#else
95+
socketFactory->loadCertificate(argv[2]);
96+
socketFactory->loadPrivateKey(argv[3]);
97+
socketFactory->loadTrustedCertificates(argv[4]);
98+
#endif
99+
trans = socketFactory->createSocket(my_addr, port);
100+
} else {
101+
trans = std::make_shared<TSocket>(my_addr, port);
102+
}
103+
104+
transport = std::make_shared<TBufferedTransport>(trans);
105+
106+
if (IS_ENABLED(CONFIG_THRIFT_COMPACT_PROTOCOL)) {
107+
protocol = std::make_shared<TCompactProtocol>(transport);
108+
} else {
109+
protocol = std::make_shared<TBinaryProtocol>(transport);
110+
}
111+
112+
HelloClient client(protocol);
113+
114+
try {
115+
transport->open();
116+
client.ping();
117+
std::string s;
118+
client.echo(s, "Hello, world!");
119+
for (int i = 0; i < 5; ++i) {
120+
client.counter();
121+
}
122+
123+
transport->close();
124+
} catch (std::exception &e) {
125+
printf("caught exception: %s\n", e.what());
126+
return EXIT_FAILURE;
127+
}
128+
129+
return EXIT_SUCCESS;
130+
}

0 commit comments

Comments
 (0)