starpc 0.52.1 → 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/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/common-rpc.d.ts +5 -0
- package/dist/srpc/common-rpc.js +37 -8
- 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/echo/Cargo.toml +8 -0
- package/echo/echo_e2e_test.cpp +542 -985
- 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 +4 -1
- package/echo/half_close_test.rs +178 -0
- package/echo/integration_server.rs +14 -21
- package/echo/main.rs +28 -48
- package/go.mod +1 -1
- package/go.sum +2 -18
- 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/mock/mock_srpc.pb.cpp +1 -1
- package/mock/mock_srpc.pb.hpp +1 -1
- package/mock/mock_srpc.pb.rs +10 -9
- package/package.json +1 -1
- package/srpc/CMakeLists.txt +3 -58
- package/srpc/README-cpp.md +69 -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_half_close_test.cc +331 -0
- package/srpc/client_invoker.rs +75 -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.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.cpp +60 -58
- package/srpc/packet.hpp +35 -20
- package/srpc/packet.rs +8 -27
- package/srpc/rpc.rs +332 -115
- package/srpc/rpc_lifecycle_test.cc +333 -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/starpc.hpp +4 -2
- package/srpc/stream.go +4 -0
- package/srpc/stream.hpp +95 -34
- package/srpc/stream.rs +7 -2
- 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
package/srpc/mux.rs
CHANGED
|
@@ -90,9 +90,7 @@ impl Mux {
|
|
|
90
90
|
let method_ids = handler.method_ids();
|
|
91
91
|
|
|
92
92
|
let mut services = self.services.write().unwrap();
|
|
93
|
-
let service_methods = services
|
|
94
|
-
.entry(service_id.to_string())
|
|
95
|
-
.or_insert_with(HashMap::new);
|
|
93
|
+
let service_methods = services.entry(service_id.to_string()).or_default();
|
|
96
94
|
|
|
97
95
|
for method_id in method_ids {
|
|
98
96
|
if !method_id.is_empty() {
|
|
@@ -346,7 +344,9 @@ mod tests {
|
|
|
346
344
|
}
|
|
347
345
|
|
|
348
346
|
// Should find the method even with empty service ID
|
|
349
|
-
let (handled, result) = mux
|
|
347
|
+
let (handled, result) = mux
|
|
348
|
+
.invoke_method("", "TestMethod", Box::new(MockStream))
|
|
349
|
+
.await;
|
|
350
350
|
assert!(handled);
|
|
351
351
|
assert!(result.is_ok());
|
|
352
352
|
}
|
package/srpc/net.go
CHANGED
|
@@ -7,12 +7,14 @@ import (
|
|
|
7
7
|
|
|
8
8
|
// Dial dials a remote server using TCP with the default muxed conn type.
|
|
9
9
|
func Dial(addr string) (Client, error) {
|
|
10
|
+
// Connect the byte stream before attaching its stream multiplexer.
|
|
10
11
|
nconn, err := net.Dial("tcp", addr)
|
|
11
12
|
if err != nil {
|
|
12
13
|
return nil, err
|
|
13
14
|
}
|
|
14
15
|
muxedConn, err := NewMuxedConn(nconn, false, nil)
|
|
15
16
|
if err != nil {
|
|
17
|
+
_ = nconn.Close()
|
|
16
18
|
return nil, err
|
|
17
19
|
}
|
|
18
20
|
return NewClientWithMuxedConn(muxedConn), nil
|
|
@@ -22,11 +24,14 @@ func Dial(addr string) (Client, error) {
|
|
|
22
24
|
// Returns on any fatal error or if ctx was canceled.
|
|
23
25
|
// errCh is an optional error channel (can be nil)
|
|
24
26
|
func Listen(ctx context.Context, addr string, srv *Server, errCh <-chan error) error {
|
|
27
|
+
// The listener and its accept routine live until this function returns.
|
|
25
28
|
lis, err := net.Listen("tcp", addr)
|
|
26
29
|
if err != nil {
|
|
27
30
|
return err
|
|
28
31
|
}
|
|
32
|
+
defer lis.Close()
|
|
29
33
|
|
|
34
|
+
// Observe serving failure alongside the caller's stop conditions.
|
|
30
35
|
listenErrCh := make(chan error, 1)
|
|
31
36
|
go func() {
|
|
32
37
|
listenErrCh <- AcceptMuxedListener(ctx, lis, srv, nil)
|
|
@@ -35,10 +40,14 @@ func Listen(ctx context.Context, addr string, srv *Server, errCh <-chan error) e
|
|
|
35
40
|
|
|
36
41
|
select {
|
|
37
42
|
case <-ctx.Done():
|
|
38
|
-
|
|
39
|
-
case err
|
|
40
|
-
return err
|
|
43
|
+
err = ctx.Err()
|
|
44
|
+
case err = <-errCh:
|
|
41
45
|
case err := <-listenErrCh:
|
|
42
46
|
return err
|
|
43
47
|
}
|
|
48
|
+
|
|
49
|
+
// Closing the listener wakes Accept; wait for its cleanup before returning.
|
|
50
|
+
_ = lis.Close()
|
|
51
|
+
<-listenErrCh
|
|
52
|
+
return err
|
|
44
53
|
}
|
package/srpc/packet.cpp
CHANGED
|
@@ -6,78 +6,80 @@
|
|
|
6
6
|
|
|
7
7
|
namespace starpc {
|
|
8
8
|
|
|
9
|
-
PacketDataHandler NewPacketDataHandler(PacketHandler handler)
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
PacketDataHandler NewPacketDataHandler(PacketHandler handler)
|
|
10
|
+
{
|
|
11
|
+
return [handler](const std::string &data) -> Error {
|
|
12
|
+
srpc::Packet pkt;
|
|
13
|
+
if (!pkt.ParseFromString(data))
|
|
14
|
+
return Error::InvalidMessage;
|
|
15
|
+
return handler(pkt);
|
|
16
|
+
};
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
Error ValidatePacket(const srpc::Packet &pkt)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
19
|
+
Error ValidatePacket(const srpc::Packet &pkt)
|
|
20
|
+
{
|
|
21
|
+
switch (pkt.body_case()) {
|
|
22
|
+
case srpc::Packet::kCallStart:
|
|
23
|
+
return ValidateCallStart(pkt.call_start());
|
|
24
|
+
case srpc::Packet::kCallData:
|
|
25
|
+
return ValidateCallData(pkt.call_data());
|
|
26
|
+
case srpc::Packet::kCallCancel:
|
|
27
|
+
return Error::OK;
|
|
28
|
+
default:
|
|
29
|
+
return Error::UnrecognizedPacket;
|
|
30
|
+
}
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
Error ValidateCallStart(const srpc::CallStart &pkt)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return Error::OK;
|
|
33
|
+
Error ValidateCallStart(const srpc::CallStart &pkt)
|
|
34
|
+
{
|
|
35
|
+
if (pkt.rpc_method().empty())
|
|
36
|
+
return Error::EmptyMethodID;
|
|
37
|
+
if (pkt.rpc_service().empty())
|
|
38
|
+
return Error::EmptyServiceID;
|
|
39
|
+
return Error::OK;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
Error ValidateCallData(const srpc::CallData &pkt)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
Error ValidateCallData(const srpc::CallData &pkt)
|
|
43
|
+
{
|
|
44
|
+
if (pkt.data().empty() && !pkt.complete() && pkt.error().empty() &&
|
|
45
|
+
!pkt.data_is_zero())
|
|
46
|
+
return Error::EmptyPacket;
|
|
47
|
+
return Error::OK;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
std::unique_ptr<srpc::Packet> NewCallStartPacket(const std::string &service,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
51
|
+
const std::string &method,
|
|
52
|
+
const std::string &data,
|
|
53
|
+
bool data_is_zero)
|
|
54
|
+
{
|
|
55
|
+
auto pkt = std::make_unique<srpc::Packet>();
|
|
56
|
+
auto *call_start = pkt->mutable_call_start();
|
|
57
|
+
call_start->set_rpc_service(service);
|
|
58
|
+
call_start->set_rpc_method(method);
|
|
59
|
+
call_start->set_data(data);
|
|
60
|
+
call_start->set_data_is_zero(data_is_zero);
|
|
61
|
+
return pkt;
|
|
61
62
|
}
|
|
62
63
|
|
|
63
64
|
std::unique_ptr<srpc::Packet> NewCallDataPacket(const std::string &data,
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
65
|
+
bool data_is_zero,
|
|
66
|
+
bool complete, Error err)
|
|
67
|
+
{
|
|
68
|
+
auto pkt = std::make_unique<srpc::Packet>();
|
|
69
|
+
auto *call_data = pkt->mutable_call_data();
|
|
70
|
+
call_data->set_data(data);
|
|
71
|
+
call_data->set_data_is_zero(data_is_zero);
|
|
72
|
+
call_data->set_complete(err != Error::OK || complete);
|
|
73
|
+
if (err != Error::OK)
|
|
74
|
+
call_data->set_error(ErrorString(err));
|
|
75
|
+
return pkt;
|
|
75
76
|
}
|
|
76
77
|
|
|
77
|
-
std::unique_ptr<srpc::Packet> NewCallCancelPacket()
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
std::unique_ptr<srpc::Packet> NewCallCancelPacket()
|
|
79
|
+
{
|
|
80
|
+
auto pkt = std::make_unique<srpc::Packet>();
|
|
81
|
+
pkt->set_call_cancel(true);
|
|
82
|
+
return pkt;
|
|
81
83
|
}
|
|
82
84
|
|
|
83
85
|
} // namespace starpc
|
package/srpc/packet.hpp
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
+
#include "errors.hpp"
|
|
4
|
+
|
|
3
5
|
#include <cstdint>
|
|
4
6
|
#include <functional>
|
|
5
7
|
#include <memory>
|
|
6
8
|
#include <string>
|
|
7
9
|
|
|
8
|
-
#include "errors.hpp"
|
|
9
|
-
|
|
10
10
|
namespace srpc {
|
|
11
11
|
class Packet;
|
|
12
12
|
class CallStart;
|
|
@@ -15,42 +15,57 @@ class CallData;
|
|
|
15
15
|
|
|
16
16
|
namespace starpc {
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
/*
|
|
19
|
+
* CloseHandler receives the transport close outcome for a stream.
|
|
20
|
+
* Matches Go CloseHandler in packet.go.
|
|
21
|
+
*/
|
|
20
22
|
using CloseHandler = std::function<void(Error close_err)>;
|
|
21
23
|
|
|
22
|
-
|
|
23
|
-
// Matches Go PacketHandler in packet.go
|
|
24
|
+
/* PacketHandler receives one parsed packet. Matches Go PacketHandler. */
|
|
24
25
|
using PacketHandler = std::function<Error(const srpc::Packet &pkt)>;
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
/*
|
|
28
|
+
* PacketDataHandler receives one packet before parsing, as its serialized
|
|
29
|
+
* bytes. Matches Go PacketDataHandler in packet.go.
|
|
30
|
+
*/
|
|
28
31
|
using PacketDataHandler = std::function<Error(const std::string &data)>;
|
|
29
32
|
|
|
30
|
-
|
|
33
|
+
/* NewPacketDataHandler parses each payload and forwards it to handler. */
|
|
31
34
|
PacketDataHandler NewPacketDataHandler(PacketHandler handler);
|
|
32
35
|
|
|
33
|
-
|
|
36
|
+
/*
|
|
37
|
+
* ValidatePacket checks a packet's shape: its body is one of the known types
|
|
38
|
+
* and the body's required fields are present.
|
|
39
|
+
*/
|
|
34
40
|
Error ValidatePacket(const srpc::Packet &pkt);
|
|
35
41
|
|
|
36
|
-
|
|
42
|
+
/* ValidateCallStart requires the service and method IDs to be present. */
|
|
37
43
|
Error ValidateCallStart(const srpc::CallStart &pkt);
|
|
38
44
|
|
|
39
|
-
|
|
45
|
+
/*
|
|
46
|
+
* ValidateCallData rejects a packet that carries no data, no completion, no
|
|
47
|
+
* error, and no zero-length marker.
|
|
48
|
+
*/
|
|
40
49
|
Error ValidateCallData(const srpc::CallData &pkt);
|
|
41
50
|
|
|
42
|
-
|
|
51
|
+
/*
|
|
52
|
+
* NewCallStartPacket builds the CallStart packet that opens a call.
|
|
53
|
+
* data_is_zero marks an intentionally empty first message.
|
|
54
|
+
*/
|
|
43
55
|
std::unique_ptr<srpc::Packet> NewCallStartPacket(const std::string &service,
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
56
|
+
const std::string &method,
|
|
57
|
+
const std::string &data,
|
|
58
|
+
bool data_is_zero);
|
|
47
59
|
|
|
48
|
-
|
|
60
|
+
/*
|
|
61
|
+
* NewCallDataPacket builds one CallData packet. err carries the call's
|
|
62
|
+
* terminal verdict; complete ends the sending side.
|
|
63
|
+
*/
|
|
49
64
|
std::unique_ptr<srpc::Packet> NewCallDataPacket(const std::string &data,
|
|
50
|
-
|
|
51
|
-
|
|
65
|
+
bool data_is_zero,
|
|
66
|
+
bool complete, Error err);
|
|
52
67
|
|
|
53
|
-
|
|
68
|
+
/* NewCallCancelPacket builds the packet that cancels the call. */
|
|
54
69
|
std::unique_ptr<srpc::Packet> NewCallCancelPacket();
|
|
55
70
|
|
|
56
71
|
} // namespace starpc
|
package/srpc/packet.rs
CHANGED
|
@@ -10,10 +10,8 @@ use bytes::Bytes;
|
|
|
10
10
|
|
|
11
11
|
/// Creates a new CallStart packet.
|
|
12
12
|
///
|
|
13
|
-
///
|
|
14
|
-
///
|
|
15
|
-
/// * `method` - The method ID
|
|
16
|
-
/// * `data` - Optional initial data (None = no data, Some(empty) = empty data)
|
|
13
|
+
/// `None` data sends no payload; `Some(empty)` sends empty data with the
|
|
14
|
+
/// `data_is_zero` flag set.
|
|
17
15
|
pub fn new_call_start(
|
|
18
16
|
service: impl Into<String>,
|
|
19
17
|
method: impl Into<String>,
|
|
@@ -31,10 +29,7 @@ pub fn new_call_start(
|
|
|
31
29
|
}
|
|
32
30
|
}
|
|
33
31
|
|
|
34
|
-
/// Creates a new CallData packet
|
|
35
|
-
///
|
|
36
|
-
/// # Arguments
|
|
37
|
-
/// * `data` - The data to send (can be empty)
|
|
32
|
+
/// Creates a new CallData packet carrying `data`, which may be empty.
|
|
38
33
|
pub fn new_call_data(data: Vec<u8>) -> Packet {
|
|
39
34
|
let data_is_zero = data.is_empty();
|
|
40
35
|
Packet {
|
|
@@ -49,16 +44,9 @@ pub fn new_call_data(data: Vec<u8>) -> Packet {
|
|
|
49
44
|
|
|
50
45
|
/// Creates a new CallData packet with optional data and flags.
|
|
51
46
|
///
|
|
52
|
-
///
|
|
53
|
-
///
|
|
54
|
-
|
|
55
|
-
/// * `complete` - True if this completes the stream
|
|
56
|
-
/// * `error` - Optional error message
|
|
57
|
-
pub fn new_call_data_full(
|
|
58
|
-
data: Option<Bytes>,
|
|
59
|
-
complete: bool,
|
|
60
|
-
error: Option<String>,
|
|
61
|
-
) -> Packet {
|
|
47
|
+
/// Sets `complete` when either `complete` or `error` is set, so an error
|
|
48
|
+
/// always ends the call.
|
|
49
|
+
pub fn new_call_data_full(data: Option<Bytes>, complete: bool, error: Option<String>) -> Packet {
|
|
62
50
|
let (data_bytes, data_is_zero) = encode_optional_data(data);
|
|
63
51
|
|
|
64
52
|
Packet {
|
|
@@ -83,10 +71,7 @@ pub fn new_call_complete() -> Packet {
|
|
|
83
71
|
}
|
|
84
72
|
}
|
|
85
73
|
|
|
86
|
-
/// Creates a new CallData packet
|
|
87
|
-
///
|
|
88
|
-
/// # Arguments
|
|
89
|
-
/// * `error` - The error message
|
|
74
|
+
/// Creates a new CallData packet carrying an error message.
|
|
90
75
|
pub fn new_call_error(error: impl Into<String>) -> Packet {
|
|
91
76
|
Packet {
|
|
92
77
|
body: Some(Body::CallData(CallData {
|
|
@@ -154,11 +139,7 @@ impl Validate for CallData {
|
|
|
154
139
|
// - data_is_zero flag set (indicating intentionally empty data)
|
|
155
140
|
// - complete flag set
|
|
156
141
|
// - error message
|
|
157
|
-
if self.data.is_empty()
|
|
158
|
-
&& !self.data_is_zero
|
|
159
|
-
&& !self.complete
|
|
160
|
-
&& self.error.is_empty()
|
|
161
|
-
{
|
|
142
|
+
if self.data.is_empty() && !self.data_is_zero && !self.complete && self.error.is_empty() {
|
|
162
143
|
return Err(Error::EmptyPacket);
|
|
163
144
|
}
|
|
164
145
|
Ok(())
|