starpc 0.8.3 → 0.8.6

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/dist/e2e/e2e.js CHANGED
@@ -8,7 +8,7 @@ async function runRPC() {
8
8
  const echoer = new EchoerServer(server);
9
9
  mux.register(createHandler(EchoerDefinition, echoer));
10
10
  const clientConn = new Conn();
11
- const serverConn = new Conn(server);
11
+ const serverConn = new Conn(server, { direction: 'inbound' });
12
12
  pipe(clientConn, serverConn, clientConn);
13
13
  const client = new Client(clientConn.buildOpenStreamFunc());
14
14
  await runRpcStreamTest(client);
@@ -5,7 +5,7 @@ async function runRPC() {
5
5
  const addr = 'ws://localhost:5000/demo';
6
6
  console.log(`Connecting to ${addr}`);
7
7
  const ws = new WebSocket(addr);
8
- const channel = new WebSocketConn(ws);
8
+ const channel = new WebSocketConn(ws, 'outbound');
9
9
  const client = channel.buildClient();
10
10
  console.log('Running client test via WebSocket..');
11
11
  await runClientTest(client);
@@ -1,10 +1,11 @@
1
- import type { Stream } from '@libp2p/interface-connection';
1
+ import type { Direction, Stream } from '@libp2p/interface-connection';
2
2
  import type { StreamMuxerFactory } from '@libp2p/interface-stream-muxer';
3
3
  import type { Duplex } from 'it-stream-types';
4
4
  import type { OpenStreamFunc, Stream as SRPCStream } from './stream.js';
5
5
  import { Client } from './client.js';
6
6
  export interface ConnParams {
7
7
  muxerFactory?: StreamMuxerFactory;
8
+ direction?: Direction;
8
9
  }
9
10
  export interface StreamHandler {
10
11
  handleStream(strm: Duplex<Uint8Array>): void;
package/dist/srpc/conn.js CHANGED
@@ -15,6 +15,7 @@ export class Conn {
15
15
  }
16
16
  this.muxer = muxerFactory.createStreamMuxer({
17
17
  onIncomingStream: this.handleIncomingStream.bind(this),
18
+ direction: connParams?.direction || 'outbound',
18
19
  });
19
20
  }
20
21
  // sink returns the message sink.
@@ -1,8 +1,9 @@
1
+ import { Direction } from '@libp2p/interface-connection';
1
2
  import type WebSocket from 'isomorphic-ws';
2
3
  import { Conn } from './conn.js';
3
4
  import { Server } from './server.js';
4
5
  export declare class WebSocketConn extends Conn {
5
6
  private socket;
6
- constructor(socket: WebSocket, server?: Server);
7
+ constructor(socket: WebSocket, direction: Direction, server?: Server);
7
8
  getSocket(): WebSocket;
8
9
  }
@@ -4,8 +4,9 @@ import { Mplex } from '@libp2p/mplex';
4
4
  import { Conn } from './conn.js';
5
5
  // WebSocketConn implements a connection with a WebSocket and optional Server.
6
6
  export class WebSocketConn extends Conn {
7
- constructor(socket, server) {
7
+ constructor(socket, direction, server) {
8
8
  super(server, {
9
+ direction,
9
10
  muxerFactory: new Mplex(),
10
11
  });
11
12
  this.socket = socket;
package/e2e/e2e.ts CHANGED
@@ -10,7 +10,7 @@ async function runRPC() {
10
10
  mux.register(createHandler(EchoerDefinition, echoer))
11
11
 
12
12
  const clientConn = new Conn()
13
- const serverConn = new Conn(server)
13
+ const serverConn = new Conn(server, {direction: 'inbound'})
14
14
  pipe(clientConn, serverConn, clientConn)
15
15
  const client = new Client(clientConn.buildOpenStreamFunc())
16
16
 
package/e2e/e2e_test.go CHANGED
@@ -32,14 +32,16 @@ func RunE2E(t *testing.T, cb func(client echo.SRPCEchoerClient) error) {
32
32
  // construct the client
33
33
  clientPipe, serverPipe := net.Pipe()
34
34
 
35
- clientMp, err := mp.NewMultiplex(clientPipe, false, nil)
35
+ // outbound=true
36
+ clientMp, err := mp.NewMultiplex(clientPipe, true, nil)
36
37
  if err != nil {
37
38
  t.Fatal(err.Error())
38
39
  }
39
40
  client := srpc.NewClientWithMuxedConn(mplex.NewMuxedConn(clientMp))
40
41
 
41
42
  ctx := context.Background()
42
- serverMp, _ := mp.NewMultiplex(serverPipe, true, nil)
43
+ // outbound=false
44
+ serverMp, _ := mp.NewMultiplex(serverPipe, false, nil)
43
45
  go func() {
44
46
  _ = server.AcceptMuxedConn(ctx, mplex.NewMuxedConn(serverMp))
45
47
  }()
package/echo/server.go CHANGED
@@ -21,6 +21,11 @@ func NewEchoServer(rpcStreamMux srpc.Mux) *EchoServer {
21
21
  return &EchoServer{rpcStreamMux: rpcStreamMux}
22
22
  }
23
23
 
24
+ // Register registers the Echo server with the Mux.
25
+ func (e *EchoServer) Register(mux srpc.Mux) error {
26
+ return SRPCRegisterEchoer(mux, e)
27
+ }
28
+
24
29
  // Echo implements echo.SRPCEchoerServer
25
30
  func (*EchoServer) Echo(ctx context.Context, msg *EchoMsg) (*EchoMsg, error) {
26
31
  return proto.Clone(msg).(*EchoMsg), nil
package/go.mod CHANGED
@@ -13,7 +13,7 @@ require (
13
13
  require (
14
14
  github.com/libp2p/go-libp2p v0.20.1-0.20220622205512-3cf611ad8c9c
15
15
  github.com/libp2p/go-libp2p-core v0.19.0
16
- github.com/libp2p/go-mplex v0.7.0
16
+ github.com/libp2p/go-mplex v0.7.1-0.20220702225122-8cbdf39b21f5
17
17
  github.com/sirupsen/logrus v1.8.2-0.20220112234510-85981c045988
18
18
  )
19
19
 
package/go.sum CHANGED
@@ -67,8 +67,8 @@ github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoR
67
67
  github.com/libp2p/go-libp2p-core v0.19.0 h1:KDw7hanmh0EuVdZqsHCAzmkdiYMk5uR5h0UGSCVTxSU=
68
68
  github.com/libp2p/go-libp2p-core v0.19.0/go.mod h1:AkA+FUKQfYt1FLNef5fOPlo/naAWjKy/RCjkcPjqzYg=
69
69
  github.com/libp2p/go-libp2p-testing v0.10.0 h1:LO7wuUPPNAe1D1s0HZ+9WoROaGIn/MEl1wtugXuTRzg=
70
- github.com/libp2p/go-mplex v0.7.0 h1:BDhFZdlk5tbr0oyFq/xv/NPGfjbnrsDam1EvutpBDbY=
71
- github.com/libp2p/go-mplex v0.7.0/go.mod h1:rW8ThnRcYWft/Jb2jeORBmPd6xuG3dGxWN/W168L9EU=
70
+ github.com/libp2p/go-mplex v0.7.1-0.20220702225122-8cbdf39b21f5 h1:ik8jmF64ZDxAn5K9zJ74ZHed6SBoomwcrP+p6QT7OOQ=
71
+ github.com/libp2p/go-mplex v0.7.1-0.20220702225122-8cbdf39b21f5/go.mod h1:rW8ThnRcYWft/Jb2jeORBmPd6xuG3dGxWN/W168L9EU=
72
72
  github.com/libp2p/go-openssl v0.0.7 h1:eCAzdLejcNVBzP/iZM9vqHnQm+XyCEbSSIheIPRGNsw=
73
73
  github.com/libp2p/go-openssl v0.0.7/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc=
74
74
  github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
@@ -6,7 +6,7 @@ async function runRPC() {
6
6
  const addr = 'ws://localhost:5000/demo'
7
7
  console.log(`Connecting to ${addr}`)
8
8
  const ws = new WebSocket(addr)
9
- const channel = new WebSocketConn(ws)
9
+ const channel = new WebSocketConn(ws, 'outbound')
10
10
  const client = channel.buildClient()
11
11
 
12
12
  console.log('Running client test via WebSocket..')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "starpc",
3
- "version": "0.8.3",
3
+ "version": "0.8.6",
4
4
  "description": "Streaming protobuf RPC service protocol over any two-way channel.",
5
5
  "license": "MIT",
6
6
  "author": {
package/srpc/accept.go CHANGED
@@ -15,7 +15,7 @@ func AcceptMuxedListener(ctx context.Context, lis net.Listener, srv *Server) err
15
15
  return err
16
16
  }
17
17
 
18
- mc, err := NewMuxedConn(nc, true)
18
+ mc, err := NewMuxedConn(nc, false)
19
19
  if err != nil {
20
20
  _ = nc.Close()
21
21
  continue
@@ -2,6 +2,7 @@ package srpc
2
2
 
3
3
  import (
4
4
  "context"
5
+ "io"
5
6
 
6
7
  "github.com/pkg/errors"
7
8
  )
@@ -86,6 +87,24 @@ func (r *ClientRPC) ReadAll() ([][]byte, error) {
86
87
  }
87
88
  }
88
89
 
90
+ // ReadOne reads a single message and returns.
91
+ //
92
+ // returns io.EOF if the stream ended.
93
+ func (r *ClientRPC) ReadOne() ([]byte, error) {
94
+ select {
95
+ case <-r.ctx.Done():
96
+ return nil, context.Canceled
97
+ case data, ok := <-r.dataCh:
98
+ if !ok {
99
+ if err := r.serverErr; err != nil {
100
+ return nil, err
101
+ }
102
+ return nil, io.EOF
103
+ }
104
+ return data, nil
105
+ }
106
+ }
107
+
89
108
  // Context is canceled when the ClientRPC is no longer valid.
90
109
  func (r *ClientRPC) Context() context.Context {
91
110
  return r.ctx
package/srpc/client.go CHANGED
@@ -2,7 +2,6 @@ package srpc
2
2
 
3
3
  import (
4
4
  "context"
5
- "io"
6
5
 
7
6
  "github.com/pkg/errors"
8
7
  )
@@ -55,17 +54,12 @@ func (c *client) Invoke(rctx context.Context, service, method string, in, out Me
55
54
  if err := clientRPC.Start(writer, true, firstMsg); err != nil {
56
55
  return err
57
56
  }
58
- msgs, err := clientRPC.ReadAll()
57
+ msg, err := clientRPC.ReadOne()
59
58
  if err != nil {
60
59
  // this includes any server returned error.
61
60
  return err
62
61
  }
63
- if len(msgs) == 0 {
64
- // no reply? return eof.
65
- return io.EOF
66
- }
67
- // parse first message to out
68
- if err := out.UnmarshalVT(msgs[0]); err != nil {
62
+ if err := out.UnmarshalVT(msg); err != nil {
69
63
  return errors.Wrap(ErrInvalidMessage, err.Error())
70
64
  }
71
65
  // done
package/srpc/conn.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Stream } from '@libp2p/interface-connection'
1
+ import type { Direction, Stream } from '@libp2p/interface-connection'
2
2
  import type {
3
3
  StreamMuxer,
4
4
  StreamMuxerFactory,
@@ -13,6 +13,9 @@ import { Client } from './client.js'
13
13
  export interface ConnParams {
14
14
  // muxerFactory overrides using the default factory (@libp2p/mplex).
15
15
  muxerFactory?: StreamMuxerFactory
16
+ // direction is the muxer connection direction.
17
+ // defaults to outbound.
18
+ direction?: Direction
16
19
  }
17
20
 
18
21
  // StreamHandler handles incoming streams.
@@ -42,6 +45,7 @@ export class Conn implements Duplex<Uint8Array> {
42
45
  }
43
46
  this.muxer = muxerFactory.createStreamMuxer({
44
47
  onIncomingStream: this.handleIncomingStream.bind(this),
48
+ direction: connParams?.direction || 'outbound',
45
49
  })
46
50
  }
47
51
 
@@ -2,6 +2,7 @@ package srpc
2
2
 
3
3
  import (
4
4
  "context"
5
+ "io"
5
6
  "net"
6
7
 
7
8
  "github.com/libp2p/go-libp2p-core/network"
@@ -9,9 +10,9 @@ import (
9
10
  mp "github.com/libp2p/go-mplex"
10
11
  )
11
12
 
12
- // NewMuxedConn constructs a new MuxedConn from a Conn.
13
- func NewMuxedConn(conn net.Conn, isServer bool) (network.MuxedConn, error) {
14
- m, err := mp.NewMultiplex(conn, isServer, nil)
13
+ // NewMuxedConn constructs a new MuxedConn from a ReadWriteCloser.
14
+ func NewMuxedConn(conn io.ReadWriteCloser, outbound bool) (network.MuxedConn, error) {
15
+ m, err := mp.NewMultiplex(conn, outbound, nil)
15
16
  if err != nil {
16
17
  return nil, err
17
18
  }
@@ -21,8 +22,8 @@ func NewMuxedConn(conn net.Conn, isServer bool) (network.MuxedConn, error) {
21
22
  // NewClientWithConn constructs the muxer and the client.
22
23
  //
23
24
  // uses libp2p mplex
24
- func NewClientWithConn(conn net.Conn, isServer bool) (Client, error) {
25
- mconn, err := NewMuxedConn(conn, isServer)
25
+ func NewClientWithConn(conn net.Conn, outbound bool) (Client, error) {
26
+ mconn, err := NewMuxedConn(conn, outbound)
26
27
  if err != nil {
27
28
  return nil, err
28
29
  }
package/srpc/packet-rw.go CHANGED
@@ -35,7 +35,15 @@ func (r *PacketReaderWriter) WritePacket(p *Packet) error {
35
35
  if err != nil {
36
36
  return err
37
37
  }
38
- _, err = r.rw.Write(data)
38
+ var n int
39
+ written := 0
40
+ for written < len(data) {
41
+ n, err = r.rw.Write(data)
42
+ if err != nil {
43
+ return err
44
+ }
45
+ written += n
46
+ }
39
47
  return err
40
48
  }
41
49
 
@@ -2,6 +2,7 @@ package srpc
2
2
 
3
3
  import (
4
4
  "context"
5
+ "io"
5
6
 
6
7
  "github.com/pkg/errors"
7
8
  )
@@ -66,12 +67,19 @@ func (r *ServerRPC) Wait(ctx context.Context) error {
66
67
 
67
68
  // HandleStreamClose handles the incoming stream closing w/ optional error.
68
69
  func (r *ServerRPC) HandleStreamClose(closeErr error) {
70
+ if r.dataChClosed {
71
+ return
72
+ }
69
73
  if closeErr != nil {
70
74
  if r.clientErr == nil {
71
75
  r.clientErr = closeErr
72
76
  }
73
- r.Close()
77
+ if closeErr != io.EOF && closeErr != context.Canceled {
78
+ r.Close()
79
+ }
74
80
  }
81
+ r.dataChClosed = true
82
+ close(r.dataCh)
75
83
  }
76
84
 
77
85
  // HandlePacket handles an incoming parsed message packet.
@@ -163,8 +171,8 @@ func (r *ServerRPC) invokeRPC() {
163
171
  }
164
172
  outPkt := NewCallDataPacket(nil, false, true, err)
165
173
  _ = r.writer.WritePacket(outPkt)
166
- r.ctxCancel()
167
174
  _ = r.writer.Close()
175
+ r.ctxCancel()
168
176
  }
169
177
 
170
178
  // Close releases any resources held by the ServerRPC.
@@ -173,9 +181,9 @@ func (r *ServerRPC) Close() {
173
181
  if r.clientErr == nil {
174
182
  r.clientErr = context.Canceled
175
183
  }
176
- r.ctxCancel()
177
184
  if r.service == "" {
178
185
  // invokeRPC has not been called, otherwise it would call Close()
179
186
  _ = r.writer.Close()
180
187
  }
188
+ r.ctxCancel()
181
189
  }
package/srpc/websocket.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { duplex } from 'it-ws'
2
2
  import { pipe } from 'it-pipe'
3
3
  import { Mplex } from '@libp2p/mplex'
4
+ import { Direction } from '@libp2p/interface-connection'
4
5
  import type WebSocket from 'isomorphic-ws'
5
6
 
6
7
  import { Conn } from './conn.js'
@@ -11,8 +12,9 @@ export class WebSocketConn extends Conn {
11
12
  // socket is the web socket
12
13
  private socket: WebSocket
13
14
 
14
- constructor(socket: WebSocket, server?: Server) {
15
+ constructor(socket: WebSocket, direction: Direction, server?: Server) {
15
16
  super(server, {
17
+ direction,
16
18
  muxerFactory: new Mplex(),
17
19
  })
18
20
  this.socket = socket