@libp2p/utils 4.0.7-9ad8f8686 → 4.0.7-adea7bbbf

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.
@@ -1,4 +1,4 @@
1
- import type { AbortOptions, ComponentLogger } from '@libp2p/interface'
1
+ import type { ComponentLogger } from '@libp2p/interface'
2
2
  import type { MultiaddrConnection, Stream } from '@libp2p/interface/connection'
3
3
  import type { Multiaddr } from '@multiformats/multiaddr'
4
4
 
@@ -15,49 +15,74 @@ export interface StreamProperties {
15
15
  */
16
16
  export function streamToMaConnection (props: StreamProperties): MultiaddrConnection {
17
17
  const { stream, remoteAddr, logger } = props
18
- const { sink, source } = stream
19
18
  const log = logger.forComponent('libp2p:stream:converter')
20
19
 
21
- const mapSource = (async function * () {
22
- for await (const list of source) {
23
- if (list instanceof Uint8Array) {
24
- yield list
25
- } else {
26
- yield * list
20
+ let closedRead = false
21
+ let closedWrite = false
22
+
23
+ // piggyback on `stream.close` invocations to close maconn
24
+ const streamClose = stream.close.bind(stream)
25
+ stream.close = async (options) => {
26
+ await streamClose(options)
27
+ close(true)
28
+ }
29
+
30
+ // piggyback on `stream.abort` invocations to close maconn
31
+ const streamAbort = stream.abort.bind(stream)
32
+ stream.abort = (err) => {
33
+ streamAbort(err)
34
+ close(true)
35
+ }
36
+
37
+ // piggyback on `stream.sink` invocations to close maconn
38
+ const streamSink = stream.sink.bind(stream)
39
+ stream.sink = async (source) => {
40
+ try {
41
+ await streamSink(source)
42
+ } catch (err: any) {
43
+ // If aborted we can safely ignore
44
+ if (err.type !== 'aborted') {
45
+ // If the source errored the socket will already have been destroyed by
46
+ // toIterable.duplex(). If the socket errored it will already be
47
+ // destroyed. There's nothing to do here except log the error & return.
48
+ log(err)
27
49
  }
50
+ } finally {
51
+ closedWrite = true
52
+ close()
28
53
  }
29
- }())
54
+ }
30
55
 
31
56
  const maConn: MultiaddrConnection = {
32
- async sink (source) {
57
+ log,
58
+ sink: stream.sink,
59
+ source: (async function * () {
33
60
  try {
34
- await sink(source)
35
- close()
36
- } catch (err: any) {
37
- // If aborted we can safely ignore
38
- if (err.type !== 'aborted') {
39
- // If the source errored the socket will already have been destroyed by
40
- // toIterable.duplex(). If the socket errored it will already be
41
- // destroyed. There's nothing to do here except log the error & return.
42
- log(err)
61
+ for await (const list of stream.source) {
62
+ if (list instanceof Uint8Array) {
63
+ yield list
64
+ } else {
65
+ yield * list
66
+ }
43
67
  }
68
+ } finally {
69
+ closedRead = true
70
+ close()
44
71
  }
45
- },
46
- source: mapSource,
72
+ }()),
47
73
  remoteAddr,
48
74
  timeline: { open: Date.now(), close: undefined },
49
- async close (options?: AbortOptions) {
50
- close()
51
- await stream.close(options)
52
- },
53
- abort (err: Error): void {
54
- close()
55
- stream.abort(err)
56
- }
75
+ close: stream.close,
76
+ abort: stream.abort
57
77
  }
58
78
 
59
- function close (): void {
60
- if (maConn.timeline.close == null) {
79
+ function close (force?: boolean): void {
80
+ if (force === true) {
81
+ closedRead = true
82
+ closedWrite = true
83
+ }
84
+
85
+ if (closedRead && closedWrite && maConn.timeline.close == null) {
61
86
  maConn.timeline.close = Date.now()
62
87
  }
63
88
  }