starpc 0.12.1 → 0.12.3

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/Makefile CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  PROTOWRAP=hack/bin/protowrap
4
4
  PROTOC_GEN_GO=hack/bin/protoc-gen-go
5
- PROTOC_GEN_GO_STARPC=hack/bin/protoc-gen-go-starpc
5
+ PROTOC_GEN_STARPC=hack/bin/protoc-gen-go-starpc
6
6
  PROTOC_GEN_VTPROTO=hack/bin/protoc-gen-go-vtproto
7
7
  GOIMPORTS=hack/bin/goimports
8
8
  GOLANGCI_LINT=hack/bin/golangci-lint
@@ -24,18 +24,18 @@ $(PROTOC_GEN_GO):
24
24
  -o ./bin/protoc-gen-go \
25
25
  google.golang.org/protobuf/cmd/protoc-gen-go
26
26
 
27
- $(PROTOC_GEN_GO_STARPC):
28
- cd ./hack; \
29
- go build -v \
30
- -o ./bin/protoc-gen-go-starpc \
31
- github.com/aperturerobotics/starpc/cmd/protoc-gen-go-starpc
32
-
33
27
  $(PROTOC_GEN_VTPROTO):
34
28
  cd ./hack; \
35
29
  go build -v \
36
30
  -o ./bin/protoc-gen-go-vtproto \
37
31
  github.com/planetscale/vtprotobuf/cmd/protoc-gen-go-vtproto
38
32
 
33
+ $(PROTOC_GEN_STARPC):
34
+ cd ./hack; \
35
+ go build -v \
36
+ -o ./bin/protoc-gen-go-starpc \
37
+ github.com/aperturerobotics/starpc/cmd/protoc-gen-go-starpc
38
+
39
39
  $(GOIMPORTS):
40
40
  cd ./hack; \
41
41
  go build -v \
@@ -46,7 +46,7 @@ $(PROTOWRAP):
46
46
  cd ./hack; \
47
47
  go build -v \
48
48
  -o ./bin/protowrap \
49
- github.com/square/goprotowrap/cmd/protowrap
49
+ github.com/aperturerobotics/goprotowrap/cmd/protowrap
50
50
 
51
51
  $(GOLANGCI_LINT):
52
52
  cd ./hack; \
@@ -61,7 +61,7 @@ $(GO_MOD_OUTDATED):
61
61
  github.com/psampaz/go-mod-outdated
62
62
 
63
63
  .PHONY: gengo
64
- gengo: $(GOIMPORTS) $(PROTOWRAP) $(PROTOC_GEN_GO) $(PROTOC_GEN_GO_STARPC) $(PROTOC_GEN_VTPROTO)
64
+ gengo: $(GOIMPORTS) $(PROTOWRAP) $(PROTOC_GEN_GO) $(PROTOC_GEN_VTPROTO) $(PROTOC_GEN_STARPC)
65
65
  go mod vendor
66
66
  shopt -s globstar; \
67
67
  set -eo pipefail; \
@@ -73,9 +73,9 @@ gengo: $(GOIMPORTS) $(PROTOWRAP) $(PROTOC_GEN_GO) $(PROTOC_GEN_GO_STARPC) $(PROT
73
73
  $(PROTOWRAP) \
74
74
  -I $$(pwd)/vendor \
75
75
  --go_out=$$(pwd)/vendor \
76
- --go-starpc_out=$$(pwd)/vendor \
77
76
  --go-vtproto_out=$$(pwd)/vendor \
78
- --go-vtproto_opt=features=marshal+unmarshal+size+equal \
77
+ --go-vtproto_opt=features=marshal+unmarshal+size+equal+clone \
78
+ --go-starpc_out=$$(pwd)/vendor \
79
79
  --proto_path $$(pwd)/vendor \
80
80
  --print_structure \
81
81
  --only_specified_files \
@@ -110,6 +110,7 @@ gents: $(PROTOWRAP) node_modules
110
110
  --ts_proto_opt=forceLong=long \
111
111
  --ts_proto_opt=oneof=unions \
112
112
  --ts_proto_opt=outputServices=default,outputServices=generic-definitions \
113
+ --ts_proto_opt=useDate=true \
113
114
  --ts_proto_opt=useAsyncIterable=true \
114
115
  --proto_path $$(pwd)/vendor \
115
116
  --print_structure \
package/README.md CHANGED
@@ -185,7 +185,7 @@ const result = await demoServiceClient.Echo({
185
185
  console.log('output', result.body)
186
186
  ```
187
187
 
188
- # Attribution
188
+ ## Attribution
189
189
 
190
190
  `protoc-gen-go-starpc` is a heavily modified version of `protoc-gen-go-drpc`.
191
191
 
@@ -199,15 +199,11 @@ Uses [vtprotobuf] to generate Protobuf marshal / unmarshal code.
199
199
 
200
200
  ## Support
201
201
 
202
- Starpc is built & supported by Aperture Robotics, LLC.
203
-
204
- Community contributions and discussion are welcomed!
205
-
206
- Please open a [GitHub issue] with any questions / issues.
202
+ Please file a [GitHub issue] and/or [Join Discord] with any questions.
207
203
 
208
204
  [GitHub issue]: https://github.com/aperturerobotics/starpc/issues/new
209
205
 
210
- ... or feel free to reach out on [Matrix Chat] or [Discord].
206
+ ... or feel free to reach out on [Matrix Chat].
211
207
 
212
- [Discord]: https://discord.gg/KJutMESRsT
208
+ [Join Discord]: https://discord.gg/KJutMESRsT
213
209
  [Matrix Chat]: https://matrix.to/#/#aperturerobotics:matrix.org
@@ -35,7 +35,9 @@ export interface Echoer {
35
35
  export declare class EchoerClientImpl implements Echoer {
36
36
  private readonly rpc;
37
37
  private readonly service;
38
- constructor(rpc: Rpc, service?: string);
38
+ constructor(rpc: Rpc, opts?: {
39
+ service?: string;
40
+ });
39
41
  Echo(request: EchoMsg): Promise<EchoMsg>;
40
42
  EchoServerStream(request: EchoMsg): AsyncIterable<EchoMsg>;
41
43
  EchoClientStream(request: AsyncIterable<EchoMsg>): Promise<EchoMsg>;
@@ -73,8 +73,8 @@ export const EchoMsg = {
73
73
  },
74
74
  };
75
75
  export class EchoerClientImpl {
76
- constructor(rpc, service) {
77
- this.service = service || "echo.Echoer";
76
+ constructor(rpc, opts) {
77
+ this.service = opts?.service || "echo.Echoer";
78
78
  this.rpc = rpc;
79
79
  this.Echo = this.Echo.bind(this);
80
80
  this.EchoServerStream = this.EchoServerStream.bind(this);
package/dist/srpc/conn.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { pipe } from 'it-pipe';
2
- import { Mplex } from '@libp2p/mplex';
2
+ import { mplex } from '@libp2p/mplex';
3
3
  import isPromise from 'is-promise';
4
4
  import { Client } from './client.js';
5
5
  import { combineUint8ArrayListTransform } from './array-list.js';
@@ -21,7 +21,7 @@ export class Conn {
21
21
  }
22
22
  let muxerFactory = connParams?.muxerFactory;
23
23
  if (!muxerFactory) {
24
- muxerFactory = new Mplex();
24
+ muxerFactory = mplex()();
25
25
  }
26
26
  this.muxer = muxerFactory.createStreamMuxer({
27
27
  onIncomingStream: this.handleIncomingStream.bind(this),
@@ -1,13 +1,13 @@
1
1
  import { duplex } from 'it-ws';
2
2
  import { pipe } from 'it-pipe';
3
- import { Mplex } from '@libp2p/mplex';
3
+ 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
7
  constructor(socket, direction, server) {
8
8
  super(server, {
9
9
  direction,
10
- muxerFactory: new Mplex(),
10
+ muxerFactory: mplex()(),
11
11
  });
12
12
  this.socket = socket;
13
13
  const socketDuplex = duplex(socket);
package/echo/echo.pb.ts CHANGED
@@ -106,8 +106,8 @@ export interface Echoer {
106
106
  export class EchoerClientImpl implements Echoer {
107
107
  private readonly rpc: Rpc;
108
108
  private readonly service: string;
109
- constructor(rpc: Rpc, service?: string) {
110
- this.service = service || "echo.Echoer";
109
+ constructor(rpc: Rpc, opts?: { service?: string }) {
110
+ this.service = opts?.service || "echo.Echoer";
111
111
  this.rpc = rpc;
112
112
  this.Echo = this.Echo.bind(this);
113
113
  this.EchoServerStream = this.EchoServerStream.bind(this);
@@ -1,5 +1,5 @@
1
1
  // Code generated by protoc-gen-srpc. DO NOT EDIT.
2
- // protoc-gen-srpc version: v0.9.2
2
+ // protoc-gen-srpc version: v0.12.3-0.20221016080028-3e0cb248fdee
3
3
  // source: github.com/aperturerobotics/starpc/echo/echo.proto
4
4
 
5
5
  package echo
@@ -9,6 +9,7 @@ import (
9
9
  io "io"
10
10
  bits "math/bits"
11
11
 
12
+ proto "google.golang.org/protobuf/proto"
12
13
  protoimpl "google.golang.org/protobuf/runtime/protoimpl"
13
14
  )
14
15
 
@@ -19,6 +20,24 @@ const (
19
20
  _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
20
21
  )
21
22
 
23
+ func (m *EchoMsg) CloneVT() *EchoMsg {
24
+ if m == nil {
25
+ return (*EchoMsg)(nil)
26
+ }
27
+ r := &EchoMsg{
28
+ Body: m.Body,
29
+ }
30
+ if len(m.unknownFields) > 0 {
31
+ r.unknownFields = make([]byte, len(m.unknownFields))
32
+ copy(r.unknownFields, m.unknownFields)
33
+ }
34
+ return r
35
+ }
36
+
37
+ func (m *EchoMsg) CloneGenericVT() proto.Message {
38
+ return m.CloneVT()
39
+ }
40
+
22
41
  func (this *EchoMsg) EqualVT(that *EchoMsg) bool {
23
42
  if this == nil {
24
43
  return that == nil
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "starpc",
3
- "version": "0.12.1",
3
+ "version": "0.12.3",
4
4
  "description": "Streaming protobuf RPC service protocol over any two-way channel.",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -59,36 +59,36 @@
59
59
  "singleQuote": true
60
60
  },
61
61
  "devDependencies": {
62
- "@typescript-eslint/eslint-plugin": "^5.40.0",
63
- "@typescript-eslint/parser": "^5.40.0",
64
- "bufferutil": "^4.0.6",
62
+ "@typescript-eslint/eslint-plugin": "^5.41.0",
63
+ "@typescript-eslint/parser": "^5.41.0",
64
+ "bufferutil": "^4.0.7",
65
65
  "depcheck": "^1.4.3",
66
- "esbuild": "^0.15.10",
67
- "eslint": "^8.25.0",
66
+ "esbuild": "^0.15.12",
67
+ "eslint": "^8.26.0",
68
68
  "eslint-config-prettier": "^8.5.0",
69
69
  "prettier": "^2.7.1",
70
70
  "rimraf": "^3.0.2",
71
- "ts-proto": "^1.126.1",
71
+ "ts-proto": "^1.130.0",
72
72
  "typescript": "^4.8.4",
73
- "utf-8-validate": "^5.0.9"
73
+ "utf-8-validate": "^5.0.10"
74
74
  },
75
75
  "dependencies": {
76
76
  "@libp2p/interface-connection": "^3.0.2",
77
77
  "@libp2p/interface-stream-muxer": "^3.0.0",
78
- "@libp2p/mplex": "^6.0.2",
78
+ "@libp2p/mplex": "^7.0.0",
79
79
  "event-iterator": "^2.0.0",
80
80
  "is-promise": "^4.0.0",
81
81
  "isomorphic-ws": "^5.0.0",
82
- "it-first": "^1.0.7",
83
- "it-length-prefixed": "^8.0.2",
82
+ "it-first": "^2.0.0",
83
+ "it-length-prefixed": "^8.0.3",
84
84
  "it-pipe": "^2.0.4",
85
85
  "it-pushable": "^3.1.0",
86
86
  "it-stream-types": "^1.0.4",
87
- "it-ws": "^5.0.2",
87
+ "it-ws": "^5.0.3",
88
88
  "long": "^5.2.0",
89
- "patch-package": "^6.4.7",
89
+ "patch-package": "^6.5.0",
90
90
  "protobufjs": "^7.1.2",
91
- "uint8arraylist": "^2.3.2",
92
- "ws": "^8.9.0"
91
+ "uint8arraylist": "^2.3.3",
92
+ "ws": "^8.10.0"
93
93
  }
94
94
  }
@@ -185,5 +185,7 @@ func (r *ClientRPC) HandleCallData(pkt *CallData) error {
185
185
  // not concurrency safe with HandlePacket.
186
186
  func (r *ClientRPC) Close() {
187
187
  r.ctxCancel()
188
- _ = r.writer.Close()
188
+ if r.writer != nil {
189
+ _ = r.writer.Close()
190
+ }
189
191
  }
@@ -0,0 +1,79 @@
1
+ package srpc
2
+
3
+ import (
4
+ "context"
5
+ "errors"
6
+ )
7
+
8
+ // ClientSet wraps a list of clients into one Client.
9
+ type ClientSet struct {
10
+ clients []Client
11
+ }
12
+
13
+ // NewClientSet constructs a new client set.
14
+ func NewClientSet(clients []Client) *ClientSet {
15
+ return &ClientSet{clients: clients}
16
+ }
17
+
18
+ // ExecCall executes a request/reply RPC with the remote.
19
+ func (c *ClientSet) ExecCall(
20
+ ctx context.Context,
21
+ service, method string,
22
+ in, out Message,
23
+ ) error {
24
+ return c.execCall(ctx, func(client Client) error {
25
+ return client.ExecCall(ctx, service, method, in, out)
26
+ })
27
+ }
28
+
29
+ // NewStream starts a streaming RPC with the remote & returns the stream.
30
+ // firstMsg is optional.
31
+ func (c *ClientSet) NewStream(
32
+ ctx context.Context,
33
+ service, method string,
34
+ firstMsg Message,
35
+ ) (Stream, error) {
36
+ var strm Stream
37
+ err := c.execCall(ctx, func(client Client) error {
38
+ var err error
39
+ strm, err = client.NewStream(ctx, service, method, firstMsg)
40
+ return err
41
+ })
42
+ return strm, err
43
+ }
44
+
45
+ // execCall executes the call conditionally retrying against subsequent client handles.
46
+ func (c *ClientSet) execCall(ctx context.Context, doCall func(client Client) error) error {
47
+ var any bool
48
+ for _, client := range c.clients {
49
+ if client == nil {
50
+ continue
51
+ }
52
+ err := doCall(client)
53
+ any = true
54
+ if err == nil {
55
+ return nil
56
+ }
57
+ if err == context.Canceled {
58
+ select {
59
+ case <-ctx.Done():
60
+ return context.Canceled
61
+ default:
62
+ continue
63
+ }
64
+ }
65
+ if err.Error() == ErrUnimplemented.Error() {
66
+ continue
67
+ }
68
+ return err
69
+ }
70
+
71
+ if !any {
72
+ return errors.New("no available rpc clients")
73
+ }
74
+
75
+ return ErrUnimplemented
76
+ }
77
+
78
+ // _ is a type assertion
79
+ var _ Client = ((*ClientSet)(nil))
package/srpc/client.go CHANGED
@@ -87,7 +87,7 @@ func (c *client) NewStream(ctx context.Context, service, method string, firstMsg
87
87
  return nil, err
88
88
  }
89
89
 
90
- return NewMsgStream(ctx, clientRPC.writer, clientRPC.dataCh), nil
90
+ return NewMsgStream(ctx, clientRPC.writer, clientRPC.dataCh, clientRPC.ctxCancel), nil
91
91
  }
92
92
 
93
93
  // _ is a type assertion
package/srpc/conn.ts CHANGED
@@ -5,7 +5,7 @@ import type {
5
5
  } from '@libp2p/interface-stream-muxer'
6
6
  import { pipe } from 'it-pipe'
7
7
  import type { Duplex } from 'it-stream-types'
8
- import { Mplex } from '@libp2p/mplex'
8
+ import { mplex } from '@libp2p/mplex'
9
9
  import { Uint8ArrayList } from 'uint8arraylist'
10
10
  import isPromise from 'is-promise'
11
11
 
@@ -55,7 +55,7 @@ export class Conn implements Duplex<Uint8Array> {
55
55
  }
56
56
  let muxerFactory = connParams?.muxerFactory
57
57
  if (!muxerFactory) {
58
- muxerFactory = new Mplex()
58
+ muxerFactory = mplex()()
59
59
  }
60
60
  this.muxer = muxerFactory.createStreamMuxer({
61
61
  onIncomingStream: this.handleIncomingStream.bind(this),
@@ -3,6 +3,7 @@ package srpc
3
3
  import (
4
4
  "context"
5
5
  "io"
6
+ "sync/atomic"
6
7
  )
7
8
 
8
9
  // MsgStream implements the stream interface passed to implementations.
@@ -13,15 +14,25 @@ type MsgStream struct {
13
14
  writer Writer
14
15
  // dataCh is the incoming data channel.
15
16
  dataCh chan []byte
17
+ // closeCb is the close callback
18
+ closeCb func()
19
+ // sendClosed indicates sending is closed.
20
+ sendClosed atomic.Bool
16
21
  }
17
22
 
18
23
  // NewMsgStream constructs a new Stream with a ClientRPC.
19
24
  // dataCh should be closed when no more messages will arrive.
20
- func NewMsgStream(ctx context.Context, writer Writer, dataCh chan []byte) *MsgStream {
25
+ func NewMsgStream(
26
+ ctx context.Context,
27
+ writer Writer,
28
+ dataCh chan []byte,
29
+ closeCb func(),
30
+ ) *MsgStream {
21
31
  return &MsgStream{
22
- ctx: ctx,
23
- writer: writer,
24
- dataCh: dataCh,
32
+ ctx: ctx,
33
+ writer: writer,
34
+ dataCh: dataCh,
35
+ closeCb: closeCb,
25
36
  }
26
37
  }
27
38
 
@@ -32,6 +43,9 @@ func (r *MsgStream) Context() context.Context {
32
43
 
33
44
  // MsgSend sends the message to the remote.
34
45
  func (r *MsgStream) MsgSend(msg Message) error {
46
+ if r.sendClosed.Load() {
47
+ return context.Canceled
48
+ }
35
49
  select {
36
50
  case <-r.ctx.Done():
37
51
  return context.Canceled
@@ -62,14 +76,34 @@ func (r *MsgStream) MsgRecv(msg Message) error {
62
76
 
63
77
  // CloseSend signals to the remote that we will no longer send any messages.
64
78
  func (r *MsgStream) CloseSend() error {
65
- outPkt := NewCallDataPacket(nil, false, true, nil)
66
- return r.writer.WritePacket(outPkt)
79
+ // if already closed, return
80
+ if r.sendClosed.Swap(true) {
81
+ return nil
82
+ }
83
+
84
+ return r.closeSend()
67
85
  }
68
86
 
69
87
  // Close closes the stream.
70
88
  func (r *MsgStream) Close() error {
71
- _ = r.writer.Close()
72
- return nil
89
+ // if already closed, return
90
+ if r.sendClosed.Swap(true) {
91
+ return nil
92
+ }
93
+
94
+ // don't close the writer: we will need to write the call result after the
95
+ // RPC function returns.
96
+ if r.closeCb != nil {
97
+ r.closeCb()
98
+ }
99
+
100
+ return r.closeSend()
101
+ }
102
+
103
+ // closeSend writes the CloseSend packet.
104
+ func (r *MsgStream) closeSend() error {
105
+ outPkt := NewCallDataPacket(nil, false, true, nil)
106
+ return r.writer.WritePacket(outPkt)
73
107
  }
74
108
 
75
109
  // _ is a type assertion
package/srpc/mux.go CHANGED
@@ -20,6 +20,9 @@ type muxMethods map[string]Handler
20
20
 
21
21
  // mux is the default implementation of Mux.
22
22
  type mux struct {
23
+ // fallback is the list of fallback invokers
24
+ // if the mux doesn't match the service, calls the invokers.
25
+ fallback []Invoker
23
26
  // rmtx guards below fields
24
27
  rmtx sync.RWMutex
25
28
  // services contains a mapping from services to handlers.
@@ -27,8 +30,14 @@ type mux struct {
27
30
  }
28
31
 
29
32
  // NewMux constructs a new Mux.
30
- func NewMux() Mux {
31
- return &mux{services: make(map[string]muxMethods)}
33
+ //
34
+ // fallbackInvokers is the list of fallback Invokers to call in the case that
35
+ // the service/method is not found on this mux.
36
+ func NewMux(fallbackInvokers ...Invoker) Mux {
37
+ return &mux{
38
+ fallback: fallbackInvokers,
39
+ services: make(map[string]muxMethods),
40
+ }
32
41
  }
33
42
 
34
43
  // Register registers a new RPC method handler (service).
@@ -95,17 +104,34 @@ func (m *mux) HasServiceMethod(serviceID, methodID string) bool {
95
104
  func (m *mux) InvokeMethod(serviceID, methodID string, strm Stream) (bool, error) {
96
105
  var handler Handler
97
106
  m.rmtx.RLock()
98
- svcMethods := m.services[serviceID]
99
- if svcMethods != nil {
100
- handler = svcMethods[methodID]
107
+ if serviceID == "" {
108
+ for _, svc := range m.services {
109
+ if handler = svc[methodID]; handler != nil {
110
+ break
111
+ }
112
+ }
113
+ } else {
114
+ svcMethods := m.services[serviceID]
115
+ if svcMethods != nil {
116
+ handler = svcMethods[methodID]
117
+ }
101
118
  }
102
119
  m.rmtx.RUnlock()
103
120
 
104
- if handler == nil {
105
- return false, nil
121
+ if handler != nil {
122
+ return handler.InvokeMethod(serviceID, methodID, strm)
123
+ }
124
+
125
+ for _, invoker := range m.fallback {
126
+ if invoker != nil {
127
+ handled, err := invoker.InvokeMethod(serviceID, methodID, strm)
128
+ if err != nil || handled {
129
+ return handled, err
130
+ }
131
+ }
106
132
  }
107
133
 
108
- return handler.InvokeMethod(serviceID, methodID, strm)
134
+ return false, nil
109
135
  }
110
136
 
111
137
  // _ is a type assertion
package/srpc/packet-rw.go CHANGED
@@ -5,6 +5,7 @@ import (
5
5
  "context"
6
6
  "encoding/binary"
7
7
  "io"
8
+ "sync"
8
9
 
9
10
  "github.com/pkg/errors"
10
11
  )
@@ -19,6 +20,8 @@ type PacketReaderWriter struct {
19
20
  rw io.ReadWriteCloser
20
21
  // buf is the buffered data
21
22
  buf bytes.Buffer
23
+ // writeMtx is the write mutex
24
+ writeMtx sync.Mutex
22
25
  }
23
26
 
24
27
  // NewPacketReadWriter constructs a new read/writer.
@@ -28,6 +31,9 @@ func NewPacketReadWriter(rw io.ReadWriteCloser) *PacketReaderWriter {
28
31
 
29
32
  // WritePacket writes a packet to the writer.
30
33
  func (r *PacketReaderWriter) WritePacket(p *Packet) error {
34
+ r.writeMtx.Lock()
35
+ defer r.writeMtx.Unlock()
36
+
31
37
  msgSize := p.SizeVT()
32
38
  data := make([]byte, 4+msgSize)
33
39
  binary.LittleEndian.PutUint32(data, uint32(msgSize))
@@ -9,6 +9,7 @@ import (
9
9
  io "io"
10
10
  bits "math/bits"
11
11
 
12
+ proto "google.golang.org/protobuf/proto"
12
13
  protoimpl "google.golang.org/protobuf/runtime/protoimpl"
13
14
  )
14
15
 
@@ -19,6 +20,95 @@ const (
19
20
  _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
20
21
  )
21
22
 
23
+ func (m *Packet) CloneVT() *Packet {
24
+ if m == nil {
25
+ return (*Packet)(nil)
26
+ }
27
+ r := &Packet{}
28
+ if m.Body != nil {
29
+ r.Body = m.Body.(interface{ CloneVT() isPacket_Body }).CloneVT()
30
+ }
31
+ if len(m.unknownFields) > 0 {
32
+ r.unknownFields = make([]byte, len(m.unknownFields))
33
+ copy(r.unknownFields, m.unknownFields)
34
+ }
35
+ return r
36
+ }
37
+
38
+ func (m *Packet) CloneGenericVT() proto.Message {
39
+ return m.CloneVT()
40
+ }
41
+
42
+ func (m *Packet_CallStart) CloneVT() isPacket_Body {
43
+ if m == nil {
44
+ return (*Packet_CallStart)(nil)
45
+ }
46
+ r := &Packet_CallStart{
47
+ CallStart: m.CallStart.CloneVT(),
48
+ }
49
+ return r
50
+ }
51
+
52
+ func (m *Packet_CallData) CloneVT() isPacket_Body {
53
+ if m == nil {
54
+ return (*Packet_CallData)(nil)
55
+ }
56
+ r := &Packet_CallData{
57
+ CallData: m.CallData.CloneVT(),
58
+ }
59
+ return r
60
+ }
61
+
62
+ func (m *CallStart) CloneVT() *CallStart {
63
+ if m == nil {
64
+ return (*CallStart)(nil)
65
+ }
66
+ r := &CallStart{
67
+ RpcService: m.RpcService,
68
+ RpcMethod: m.RpcMethod,
69
+ DataIsZero: m.DataIsZero,
70
+ }
71
+ if rhs := m.Data; rhs != nil {
72
+ tmpBytes := make([]byte, len(rhs))
73
+ copy(tmpBytes, rhs)
74
+ r.Data = tmpBytes
75
+ }
76
+ if len(m.unknownFields) > 0 {
77
+ r.unknownFields = make([]byte, len(m.unknownFields))
78
+ copy(r.unknownFields, m.unknownFields)
79
+ }
80
+ return r
81
+ }
82
+
83
+ func (m *CallStart) CloneGenericVT() proto.Message {
84
+ return m.CloneVT()
85
+ }
86
+
87
+ func (m *CallData) CloneVT() *CallData {
88
+ if m == nil {
89
+ return (*CallData)(nil)
90
+ }
91
+ r := &CallData{
92
+ DataIsZero: m.DataIsZero,
93
+ Complete: m.Complete,
94
+ Error: m.Error,
95
+ }
96
+ if rhs := m.Data; rhs != nil {
97
+ tmpBytes := make([]byte, len(rhs))
98
+ copy(tmpBytes, rhs)
99
+ r.Data = tmpBytes
100
+ }
101
+ if len(m.unknownFields) > 0 {
102
+ r.unknownFields = make([]byte, len(m.unknownFields))
103
+ copy(r.unknownFields, m.unknownFields)
104
+ }
105
+ return r
106
+ }
107
+
108
+ func (m *CallData) CloneGenericVT() proto.Message {
109
+ return m.CloneVT()
110
+ }
111
+
22
112
  func (this *Packet) EqualVT(that *Packet) bool {
23
113
  if this == nil {
24
114
  return that == nil
@@ -164,7 +164,7 @@ func (r *ServerRPC) HandleCallData(pkt *CallData) error {
164
164
  func (r *ServerRPC) invokeRPC() {
165
165
  // ctx := r.ctx
166
166
  serviceID, methodID := r.service, r.method
167
- strm := NewMsgStream(r.ctx, r.writer, r.dataCh)
167
+ strm := NewMsgStream(r.ctx, r.writer, r.dataCh, r.ctxCancel)
168
168
  ok, err := r.invoker.InvokeMethod(serviceID, methodID, strm)
169
169
  if err == nil && !ok {
170
170
  err = ErrUnimplemented
@@ -181,7 +181,7 @@ func (r *ServerRPC) Close() {
181
181
  if r.clientErr == nil {
182
182
  r.clientErr = context.Canceled
183
183
  }
184
- if r.service == "" {
184
+ if r.writer != nil && r.service == "" {
185
185
  // invokeRPC has not been called, otherwise it would call Close()
186
186
  _ = r.writer.Close()
187
187
  }
package/srpc/websocket.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { duplex } from 'it-ws'
2
2
  import { pipe } from 'it-pipe'
3
- import { Mplex } from '@libp2p/mplex'
3
+ import { mplex } from '@libp2p/mplex'
4
4
  import { Direction } from '@libp2p/interface-connection'
5
5
  import type WebSocket from 'isomorphic-ws'
6
6
 
@@ -15,7 +15,7 @@ export class WebSocketConn extends Conn {
15
15
  constructor(socket: WebSocket, direction: Direction, server?: Server) {
16
16
  super(server, {
17
17
  direction,
18
- muxerFactory: new Mplex(),
18
+ muxerFactory: mplex()(),
19
19
  })
20
20
  this.socket = socket
21
21
  const socketDuplex = duplex(socket)