starpc 0.52.0 → 0.52.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -8
- package/dist/echo/client-test.d.ts +1 -1
- package/dist/echo/client-test.js +110 -2
- package/dist/integration/cross-language/tcp-packet-stream.d.ts +3 -0
- package/dist/integration/cross-language/tcp-packet-stream.js +112 -0
- package/dist/integration/cross-language/tcp-packet-stream.test.d.ts +1 -0
- package/dist/integration/cross-language/tcp-packet-stream.test.js +121 -0
- package/dist/integration/cross-language/ts-client.js +50 -37
- package/dist/integration/cross-language/ts-server.js +1 -36
- package/dist/rpcstream/rpcstream.d.ts +5 -1
- package/dist/rpcstream/rpcstream.js +75 -28
- package/dist/rpcstream/rpcstream.test.d.ts +1 -0
- package/dist/rpcstream/rpcstream.test.js +92 -0
- package/dist/srpc/client-rpc.d.ts +1 -0
- package/dist/srpc/client-rpc.js +9 -0
- package/dist/srpc/client-rpc.test.d.ts +1 -0
- package/dist/srpc/client-rpc.test.js +50 -0
- package/dist/srpc/client.js +18 -4
- package/dist/srpc/common-rpc.d.ts +5 -0
- package/dist/srpc/common-rpc.js +37 -8
- package/dist/srpc/common-rpc.test.js +2 -0
- package/dist/srpc/errors.d.ts +2 -0
- package/dist/srpc/errors.js +14 -0
- package/dist/srpc/index.d.ts +1 -1
- package/dist/srpc/index.js +1 -1
- package/dist/srpc/packet-codec.test.d.ts +1 -0
- package/dist/srpc/packet-codec.test.js +75 -0
- package/dist/srpc/packet.d.ts +1 -1
- package/dist/srpc/packet.js +11 -1
- package/dist/srpc/server.js +19 -6
- package/dist/srpc/server.test.js +43 -0
- package/dist/srpc/stream.d.ts +4 -1
- package/dist/srpc/stream.js +62 -3
- package/dist/srpc/stream.test.js +110 -1
- package/dist/srpc/termination.d.ts +27 -0
- package/dist/srpc/termination.js +56 -0
- package/dist/srpc/termination.test.d.ts +1 -0
- package/dist/srpc/termination.test.js +24 -0
- package/dist/testdata/packet-codec-vectors.json +64 -0
- package/echo/Cargo.toml +8 -0
- package/echo/client-test.ts +124 -2
- package/echo/echo_e2e_test.cpp +542 -985
- package/echo/echo_pb2.py +40 -0
- package/echo/echo_pb2.pyi +13 -0
- package/echo/echo_srpc.pb.cpp +3 -5
- package/echo/echo_srpc.pb.go +6 -9
- package/echo/echo_srpc.pb.hpp +23 -3
- package/echo/echo_srpc.pb.rs +61 -26
- package/echo/echo_srpc.py +309 -0
- package/echo/echo_srpc.pyi +85 -0
- package/echo/half_close_test.rs +178 -0
- package/echo/integration_server.rs +14 -21
- package/echo/main.rs +28 -48
- package/go.mod +3 -3
- package/go.sum +6 -8
- package/integration/cross-language/cpp-client.cpp +446 -402
- package/integration/cross-language/cpp-pipe-server.cpp +139 -0
- package/integration/cross-language/cpp-pipe_test.go +114 -0
- package/integration/cross-language/cpp-server.cpp +222 -186
- package/integration/cross-language/go-client/main.go +79 -3
- package/integration/cross-language/python-client.py +146 -0
- package/integration/cross-language/python-server.py +140 -0
- package/integration/cross-language/run.bash +190 -65
- package/integration/cross-language/tcp-packet-stream.test.ts +154 -0
- package/integration/cross-language/tcp-packet-stream.ts +121 -0
- package/integration/cross-language/ts-client.ts +62 -40
- package/integration/cross-language/ts-server.ts +1 -45
- package/mock/mock_pb2.py +38 -0
- package/mock/mock_pb2.pyi +11 -0
- package/mock/mock_srpc.pb.cpp +1 -1
- package/mock/mock_srpc.pb.hpp +1 -1
- package/mock/mock_srpc.pb.rs +10 -9
- package/mock/mock_srpc.py +71 -0
- package/mock/mock_srpc.pyi +27 -0
- package/package.json +19 -5
- package/srpc/CMakeLists.txt +3 -58
- package/srpc/README-cpp.md +69 -0
- package/srpc/__init__.py +0 -0
- package/srpc/accept.go +10 -4
- package/srpc/accept_test.go +25 -0
- package/srpc/build.rs +129 -34
- package/srpc/client-half-close_test.go +152 -0
- package/srpc/client-invoker.go +32 -42
- package/srpc/client-invoker_test.go +53 -0
- package/srpc/client-rpc.cpp +65 -80
- package/srpc/client-rpc.go +32 -33
- package/srpc/client-rpc.hpp +52 -38
- package/srpc/client-rpc.test.ts +67 -0
- package/srpc/client-rpc.ts +10 -0
- package/srpc/client-rpc_test.go +76 -0
- package/srpc/client.cpp +99 -87
- package/srpc/client.hpp +46 -35
- package/srpc/client.rs +78 -38
- package/srpc/client.ts +20 -4
- package/srpc/client_half_close_test.cc +331 -0
- package/srpc/client_invoker.rs +75 -0
- package/srpc/codec.rs +6 -0
- package/srpc/common-rpc.cpp +186 -146
- package/srpc/common-rpc.go +5 -4
- package/srpc/common-rpc.hpp +119 -89
- package/srpc/common-rpc.test.ts +2 -0
- package/srpc/common-rpc.ts +43 -8
- package/srpc/common-rpc_test.go +23 -0
- package/srpc/error.rs +19 -2
- package/srpc/errors.hpp +80 -50
- package/srpc/errors.ts +16 -0
- package/srpc/handler.hpp +9 -7
- package/srpc/handler.rs +7 -45
- package/srpc/index.ts +2 -0
- package/srpc/invoker.hpp +82 -55
- package/srpc/invoker.rs +14 -52
- package/srpc/lib.rs +2 -0
- package/srpc/message.hpp +17 -12
- package/srpc/msg-stream.go +1 -0
- package/srpc/msg-stream.hpp +108 -61
- package/srpc/mux.cpp +84 -84
- package/srpc/mux.hpp +48 -38
- package/srpc/mux.rs +4 -4
- package/srpc/net.go +12 -3
- package/srpc/packet-codec-vectors_test.go +195 -0
- package/srpc/packet-codec.test.ts +139 -0
- package/srpc/packet-rw.go +9 -2
- package/srpc/packet.cpp +60 -58
- package/srpc/packet.hpp +35 -20
- package/srpc/packet.rs +8 -27
- package/srpc/packet.ts +15 -2
- package/srpc/py.typed +0 -0
- package/srpc/rpc.rs +332 -115
- package/srpc/rpc_lifecycle_test.cc +333 -0
- package/srpc/rpcproto_pb2.py +40 -0
- package/srpc/rpcproto_pb2.pyi +40 -0
- package/srpc/server-cancel_test.go +39 -0
- package/srpc/server-rpc.cpp +83 -73
- package/srpc/server-rpc.go +21 -19
- package/srpc/server-rpc.hpp +56 -37
- package/srpc/server.rs +76 -131
- package/srpc/server.test.ts +50 -0
- package/srpc/server.ts +22 -6
- package/srpc/starpc.hpp +4 -2
- package/srpc/stream.go +4 -0
- package/srpc/stream.hpp +95 -34
- package/srpc/stream.rs +7 -2
- package/srpc/stream.test.ts +132 -1
- package/srpc/stream.ts +65 -9
- package/srpc/termination.test.ts +30 -0
- package/srpc/termination.ts +70 -0
- package/srpc/testing.rs +11 -66
- package/srpc/transport.rs +21 -71
- package/srpc/websocket.rs +106 -57
- package/srpc/writer.hpp +46 -32
- package/srpc/yamux.rs +82 -26
- package/srpc/tests/integration_test.rs +0 -495
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
//go:build deps_only
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
/*
|
|
4
|
+
* C++ TCP integration server for cross-language testing: it listens on TCP
|
|
5
|
+
* and serves one RPC per connection over length-prefixed packets.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#include "echo/echo_srpc.pb.hpp"
|
|
9
|
+
#include "rpcstream/rpcstream.hpp"
|
|
10
|
+
#include "srpc/rpcproto.pb.h"
|
|
11
|
+
#include "srpc/starpc.hpp"
|
|
5
12
|
|
|
6
13
|
#include <arpa/inet.h>
|
|
7
14
|
#include <csignal>
|
|
@@ -13,209 +20,238 @@
|
|
|
13
20
|
#include <sys/socket.h>
|
|
14
21
|
#include <thread>
|
|
15
22
|
#include <unistd.h>
|
|
16
|
-
|
|
17
|
-
#include "echo/echo_srpc.pb.hpp"
|
|
18
|
-
#include "rpcstream/rpcstream.hpp"
|
|
19
|
-
#include "srpc/rpcproto.pb.h"
|
|
20
|
-
#include "srpc/starpc.hpp"
|
|
23
|
+
#include <vector>
|
|
21
24
|
|
|
22
25
|
namespace {
|
|
23
26
|
|
|
24
|
-
|
|
25
|
-
bool ReadFull(int fd, void *buf, size_t n)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
/* ReadFull reads exactly n bytes from fd, reporting short reads as false. */
|
|
28
|
+
bool ReadFull(int fd, void *buf, size_t n)
|
|
29
|
+
{
|
|
30
|
+
size_t total = 0;
|
|
31
|
+
while (total < n) {
|
|
32
|
+
ssize_t r =
|
|
33
|
+
read(fd, static_cast<char *>(buf) + total, n - total);
|
|
34
|
+
if (r <= 0)
|
|
35
|
+
return false;
|
|
36
|
+
total += r;
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
34
39
|
}
|
|
35
40
|
|
|
36
|
-
|
|
37
|
-
bool WriteFull(int fd, const void *buf, size_t n)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
/* WriteFull writes exactly n bytes to fd, reporting short writes as false. */
|
|
42
|
+
bool WriteFull(int fd, const void *buf, size_t n)
|
|
43
|
+
{
|
|
44
|
+
size_t total = 0;
|
|
45
|
+
while (total < n) {
|
|
46
|
+
ssize_t w = write(fd, static_cast<const char *>(buf) + total,
|
|
47
|
+
n - total);
|
|
48
|
+
if (w <= 0)
|
|
49
|
+
return false;
|
|
50
|
+
total += w;
|
|
51
|
+
}
|
|
52
|
+
return true;
|
|
46
53
|
}
|
|
47
54
|
|
|
48
|
-
|
|
55
|
+
/*
|
|
56
|
+
* TcpPacketWriter writes length-prefixed packets to a TCP socket. The fd is
|
|
57
|
+
* borrowed and closed by the connection handler, not the writer.
|
|
58
|
+
*/
|
|
49
59
|
class TcpPacketWriter : public starpc::PacketWriter {
|
|
50
60
|
public:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
61
|
+
explicit TcpPacketWriter(int fd)
|
|
62
|
+
: fd(fd)
|
|
63
|
+
{
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
starpc::Error WritePacket(const srpc::Packet &pkt) override
|
|
67
|
+
{
|
|
68
|
+
std::lock_guard<std::mutex> lock(mu);
|
|
69
|
+
|
|
70
|
+
std::string data;
|
|
71
|
+
if (!pkt.SerializeToString(&data))
|
|
72
|
+
return starpc::Error::InvalidMessage;
|
|
73
|
+
|
|
74
|
+
/* The length prefix is a little-endian uint32. */
|
|
75
|
+
uint32_t len = static_cast<uint32_t>(data.size());
|
|
76
|
+
if (!WriteFull(fd, &len, 4))
|
|
77
|
+
return starpc::Error::EOF_;
|
|
78
|
+
if (!WriteFull(fd, data.data(), data.size()))
|
|
79
|
+
return starpc::Error::EOF_;
|
|
80
|
+
return starpc::Error::OK;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
starpc::Error Close() override
|
|
84
|
+
{
|
|
85
|
+
shutdown(fd, SHUT_WR);
|
|
86
|
+
return starpc::Error::OK;
|
|
87
|
+
}
|
|
72
88
|
|
|
73
89
|
private:
|
|
74
|
-
|
|
75
|
-
|
|
90
|
+
int fd;
|
|
91
|
+
std::mutex mu;
|
|
76
92
|
};
|
|
77
93
|
|
|
78
|
-
|
|
94
|
+
/* EchoServerImpl implements the echo service under test. */
|
|
79
95
|
class EchoServerImpl : public echo::SRPCEchoerServer {
|
|
80
96
|
public:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
97
|
+
starpc::Error Echo(const echo::EchoMsg &req,
|
|
98
|
+
echo::EchoMsg *resp) override
|
|
99
|
+
{
|
|
100
|
+
resp->set_body(req.body());
|
|
101
|
+
return starpc::Error::OK;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
starpc::Error
|
|
105
|
+
EchoServerStream(const echo::EchoMsg &req,
|
|
106
|
+
echo::SRPCEchoer_EchoServerStreamStream *strm) override
|
|
107
|
+
{
|
|
108
|
+
for (int i = 0; i < 5; i++) {
|
|
109
|
+
echo::EchoMsg msg;
|
|
110
|
+
msg.set_body(req.body());
|
|
111
|
+
starpc::Error err = strm->Send(msg);
|
|
112
|
+
if (err != starpc::Error::OK)
|
|
113
|
+
return err;
|
|
114
|
+
}
|
|
115
|
+
return starpc::Error::OK;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
starpc::Error
|
|
119
|
+
EchoClientStream(echo::SRPCEchoer_EchoClientStreamStream *strm,
|
|
120
|
+
echo::EchoMsg *resp) override
|
|
121
|
+
{
|
|
122
|
+
echo::EchoMsg msg;
|
|
123
|
+
starpc::Error err = strm->Recv(&msg);
|
|
124
|
+
if (err != starpc::Error::OK)
|
|
125
|
+
return err;
|
|
126
|
+
resp->set_body(msg.body());
|
|
127
|
+
return starpc::Error::OK;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
starpc::Error
|
|
131
|
+
EchoBidiStream(echo::SRPCEchoer_EchoBidiStreamStream *strm) override
|
|
132
|
+
{
|
|
133
|
+
/* Send the initial message the other clients expect. */
|
|
134
|
+
echo::EchoMsg init;
|
|
135
|
+
init.set_body("hello from server");
|
|
136
|
+
starpc::Error err = strm->Send(init);
|
|
137
|
+
if (err != starpc::Error::OK)
|
|
138
|
+
return err;
|
|
139
|
+
|
|
140
|
+
while (true) {
|
|
141
|
+
echo::EchoMsg msg;
|
|
142
|
+
err = strm->Recv(&msg);
|
|
143
|
+
if (err == starpc::Error::EOF_)
|
|
144
|
+
break;
|
|
145
|
+
if (err != starpc::Error::OK)
|
|
146
|
+
return err;
|
|
147
|
+
err = strm->Send(msg);
|
|
148
|
+
if (err != starpc::Error::OK)
|
|
149
|
+
return err;
|
|
150
|
+
}
|
|
151
|
+
return starpc::Error::OK;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
starpc::Error RpcStream(echo::SRPCEchoer_RpcStreamStream *) override
|
|
155
|
+
{
|
|
156
|
+
return starpc::Error::Unimplemented;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
starpc::Error DoNothing(const google::protobuf::Empty &,
|
|
160
|
+
google::protobuf::Empty *) override
|
|
161
|
+
{
|
|
162
|
+
return starpc::Error::OK;
|
|
163
|
+
}
|
|
140
164
|
};
|
|
141
165
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
166
|
+
/*
|
|
167
|
+
* HandleConnection serves one TCP connection: it reads length-prefixed
|
|
168
|
+
* packets until the socket ends, then closes the fd.
|
|
169
|
+
*/
|
|
170
|
+
void HandleConnection(int fd, starpc::Mux *mux)
|
|
171
|
+
{
|
|
172
|
+
auto writer = std::make_unique<TcpPacketWriter>(fd);
|
|
173
|
+
auto server_rpc = starpc::NewServerRPC(mux, writer.get());
|
|
174
|
+
|
|
175
|
+
while (true) {
|
|
176
|
+
/* The length prefix is a little-endian uint32. */
|
|
177
|
+
uint32_t len = 0;
|
|
178
|
+
if (!ReadFull(fd, &len, 4))
|
|
179
|
+
break;
|
|
180
|
+
|
|
181
|
+
std::string data(len, '\0');
|
|
182
|
+
if (!ReadFull(fd, data.data(), len))
|
|
183
|
+
break;
|
|
184
|
+
|
|
185
|
+
starpc::Error err = server_rpc->HandlePacketData(data);
|
|
186
|
+
if (err != starpc::Error::OK && err != starpc::Error::Completed)
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
close(fd);
|
|
164
191
|
}
|
|
165
192
|
|
|
166
193
|
} // namespace
|
|
167
194
|
|
|
168
|
-
int main()
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
195
|
+
int main()
|
|
196
|
+
{
|
|
197
|
+
signal(SIGPIPE, SIG_IGN);
|
|
198
|
+
|
|
199
|
+
auto mux = starpc::NewMux();
|
|
200
|
+
EchoServerImpl server;
|
|
201
|
+
auto [handler, err] = echo::SRPCRegisterEchoer(mux.get(), &server);
|
|
202
|
+
(void)handler;
|
|
203
|
+
if (err != starpc::Error::OK) {
|
|
204
|
+
std::cerr << "register error: " << starpc::ErrorString(err)
|
|
205
|
+
<< std::endl;
|
|
206
|
+
return 1;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
|
210
|
+
if (sockfd < 0) {
|
|
211
|
+
std::cerr << "socket error" << std::endl;
|
|
212
|
+
return 1;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
int opt = 1;
|
|
216
|
+
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
|
|
217
|
+
|
|
218
|
+
struct sockaddr_in addr{};
|
|
219
|
+
addr.sin_family = AF_INET;
|
|
220
|
+
addr.sin_port = 0; /* OS-assigned port. */
|
|
221
|
+
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
|
222
|
+
|
|
223
|
+
if (bind(sockfd, reinterpret_cast<struct sockaddr *>(&addr),
|
|
224
|
+
sizeof(addr)) < 0) {
|
|
225
|
+
std::cerr << "bind error" << std::endl;
|
|
226
|
+
close(sockfd);
|
|
227
|
+
return 1;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (listen(sockfd, 10) < 0) {
|
|
231
|
+
std::cerr << "listen error" << std::endl;
|
|
232
|
+
close(sockfd);
|
|
233
|
+
return 1;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/* Report the assigned port so the test driver can connect. */
|
|
237
|
+
socklen_t addr_len = sizeof(addr);
|
|
238
|
+
getsockname(sockfd, reinterpret_cast<struct sockaddr *>(&addr),
|
|
239
|
+
&addr_len);
|
|
240
|
+
std::cout << "LISTENING 127.0.0.1:" << ntohs(addr.sin_port)
|
|
241
|
+
<< std::endl;
|
|
242
|
+
|
|
243
|
+
/* Connection threads borrow mux, so join them before it ends. */
|
|
244
|
+
std::vector<std::thread> connections;
|
|
245
|
+
while (true) {
|
|
246
|
+
int client_fd = accept(sockfd, nullptr, nullptr);
|
|
247
|
+
if (client_fd < 0)
|
|
248
|
+
break;
|
|
249
|
+
connections.emplace_back(HandleConnection, client_fd,
|
|
250
|
+
mux.get());
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
close(sockfd);
|
|
254
|
+
for (auto &connection : connections)
|
|
255
|
+
connection.join();
|
|
256
|
+
return 0;
|
|
221
257
|
}
|
|
@@ -6,19 +6,23 @@ import (
|
|
|
6
6
|
"io"
|
|
7
7
|
"net"
|
|
8
8
|
"os"
|
|
9
|
+
"strings"
|
|
9
10
|
|
|
10
11
|
"github.com/aperturerobotics/starpc/echo"
|
|
12
|
+
"github.com/aperturerobotics/starpc/rpcstream"
|
|
11
13
|
"github.com/aperturerobotics/starpc/srpc"
|
|
12
14
|
)
|
|
13
15
|
|
|
14
16
|
const bodyTxt = "hello world via starpc cross-language e2e test"
|
|
15
17
|
|
|
16
18
|
func main() {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
nested := len(os.Args) >= 3 && os.Args[1] == "--nested"
|
|
20
|
+
nestedRelease := len(os.Args) >= 3 && os.Args[1] == "--nested-release"
|
|
21
|
+
if len(os.Args) != 2 && !nested && !nestedRelease {
|
|
22
|
+
fmt.Fprintf(os.Stderr, "usage: go-client [--nested] <addr>\n")
|
|
19
23
|
os.Exit(1)
|
|
20
24
|
}
|
|
21
|
-
addr := os.Args[1]
|
|
25
|
+
addr := os.Args[len(os.Args)-1]
|
|
22
26
|
openStream := func(ctx context.Context, msgHandler srpc.PacketDataHandler, closeHandler srpc.CloseHandler) (srpc.PacketWriter, error) {
|
|
23
27
|
conn, err := net.Dial("tcp", addr) //nolint:gosec
|
|
24
28
|
if err != nil {
|
|
@@ -48,6 +52,12 @@ func main() {
|
|
|
48
52
|
fmt.Fprintf(os.Stderr, "bidi stream test failed: %v\n", err)
|
|
49
53
|
os.Exit(1)
|
|
50
54
|
}
|
|
55
|
+
if nested || nestedRelease {
|
|
56
|
+
if err := testNested(ctx, echoClient, nestedRelease); err != nil {
|
|
57
|
+
fmt.Fprintf(os.Stderr, "nested lifecycle test failed: %v\n", err)
|
|
58
|
+
os.Exit(1)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
51
61
|
fmt.Println("All tests passed.")
|
|
52
62
|
}
|
|
53
63
|
|
|
@@ -143,3 +153,69 @@ func testBidiStream(ctx context.Context, client echo.SRPCEchoerClient) error {
|
|
|
143
153
|
fmt.Println(" PASSED")
|
|
144
154
|
return nil
|
|
145
155
|
}
|
|
156
|
+
|
|
157
|
+
func testNested(ctx context.Context, parent echo.SRPCEchoerClient, release bool) error {
|
|
158
|
+
proxy := rpcstream.NewRpcStreamClient(parent.RpcStream, "test", true)
|
|
159
|
+
if err := testUnary(ctx, echo.NewSRPCEchoerClient(proxy)); err != nil {
|
|
160
|
+
return fmt.Errorf("nested unary: %w", err)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if release {
|
|
164
|
+
missing := rpcstream.NewRpcStreamClient(parent.RpcStream, "missing", true)
|
|
165
|
+
var missingOut echo.EchoMsg
|
|
166
|
+
if err := missing.ExecCall(ctx, "echo.Echoer", "Echo", &echo.EchoMsg{}, &missingOut); err == nil || !strings.Contains(err.Error(), "unknown component: missing") {
|
|
167
|
+
return fmt.Errorf("unknown component returned wrong result: %v", err)
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
stream, err := proxy.NewStream(ctx, "echo.Echoer", "EchoBidiStream", nil)
|
|
172
|
+
if err != nil {
|
|
173
|
+
return fmt.Errorf("nested bidi: %w", err)
|
|
174
|
+
}
|
|
175
|
+
if err := stream.MsgSend(&echo.EchoMsg{Body: "nested later data"}); err != nil {
|
|
176
|
+
return fmt.Errorf("nested later data: %w", err)
|
|
177
|
+
}
|
|
178
|
+
if err := stream.Close(); err != nil {
|
|
179
|
+
return fmt.Errorf("nested cancel: %w", err)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
var terminal echo.EchoMsg
|
|
183
|
+
if err := proxy.ExecCall(ctx, "missing.Service", "Missing", &echo.EchoMsg{}, &terminal); err == nil || !strings.Contains(err.Error(), "missing.Service") {
|
|
184
|
+
return fmt.Errorf("unknown nested method returned wrong result: %v", err)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if release {
|
|
188
|
+
var terminalError echo.EchoMsg
|
|
189
|
+
if err := proxy.ExecCall(ctx, "echo.Echoer", "Echo", &echo.EchoMsg{Body: "__nested_error__"}, &terminalError); err == nil || !strings.Contains(err.Error(), "nested terminal error") {
|
|
190
|
+
return fmt.Errorf("terminal nested error returned wrong result: %v", err)
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if release {
|
|
195
|
+
releaseClient := rpcstream.NewRpcStreamClient(parent.RpcStream, "release", true)
|
|
196
|
+
var released echo.EchoMsg
|
|
197
|
+
err := releaseClient.ExecCall(ctx, "echo.Echoer", "Echo", &echo.EchoMsg{Body: "__nested_release__"}, &released)
|
|
198
|
+
if err == nil || (!strings.Contains(err.Error(), "stream closed before the remote reported completion") && !strings.Contains(err.Error(), "EOF") && !strings.Contains(err.Error(), "canceled")) {
|
|
199
|
+
return fmt.Errorf("release during active call returned wrong result: %v", err)
|
|
200
|
+
}
|
|
201
|
+
status, err := parent.Echo(ctx, &echo.EchoMsg{Body: "__nested_release_status__"})
|
|
202
|
+
if err != nil {
|
|
203
|
+
return fmt.Errorf("release completion status failed: %w", err)
|
|
204
|
+
}
|
|
205
|
+
if status.GetBody() != "released" {
|
|
206
|
+
return fmt.Errorf("release completion returned %q", status.GetBody())
|
|
207
|
+
}
|
|
208
|
+
if err := releaseClient.ExecCall(ctx, "echo.Echoer", "Echo", &echo.EchoMsg{}, &released); err == nil || !strings.Contains(err.Error(), "unknown component: release") {
|
|
209
|
+
return fmt.Errorf("released component returned wrong result: %v", err)
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
direct, err := rpcstream.OpenRpcStream(ctx, parent.RpcStream, "test", true)
|
|
214
|
+
if err != nil {
|
|
215
|
+
return fmt.Errorf("nested direct open: %w", err)
|
|
216
|
+
}
|
|
217
|
+
if err := direct.Close(); err != nil {
|
|
218
|
+
return fmt.Errorf("nested abrupt close: %w", err)
|
|
219
|
+
}
|
|
220
|
+
return nil
|
|
221
|
+
}
|