@olane/o-node 0.7.40 → 0.7.42
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/src/connection/index.d.ts +1 -1
- package/dist/src/connection/index.d.ts.map +1 -1
- package/dist/src/connection/index.js +1 -1
- package/dist/src/connection/interfaces/o-node-connection-stream.config.d.ts +8 -0
- package/dist/src/connection/interfaces/o-node-connection-stream.config.d.ts.map +1 -0
- package/dist/src/connection/interfaces/o-node-connection-stream.config.js +1 -0
- package/dist/src/connection/o-node-connection-stream.d.ts +34 -0
- package/dist/src/connection/o-node-connection-stream.d.ts.map +1 -0
- package/dist/src/connection/o-node-connection-stream.js +68 -0
- package/dist/src/connection/o-node-connection.d.ts +10 -4
- package/dist/src/connection/o-node-connection.d.ts.map +1 -1
- package/dist/src/connection/o-node-connection.js +51 -34
- package/dist/src/connection/o-node-connection.manager.d.ts +4 -0
- package/dist/src/connection/o-node-connection.manager.d.ts.map +1 -1
- package/dist/src/connection/o-node-connection.manager.js +24 -0
- package/dist/src/connection/stream-handler.d.ts +1 -59
- package/dist/src/connection/stream-handler.d.ts.map +1 -1
- package/dist/src/connection/stream-handler.js +104 -179
- package/dist/src/o-node.tool.d.ts +3 -1
- package/dist/src/o-node.tool.d.ts.map +1 -1
- package/dist/src/o-node.tool.js +44 -11
- package/dist/src/router/o-node.address.d.ts +1 -0
- package/dist/src/router/o-node.address.d.ts.map +1 -1
- package/dist/src/router/o-node.address.js +4 -0
- package/dist/src/utils/connection.utils.d.ts +9 -0
- package/dist/src/utils/connection.utils.d.ts.map +1 -0
- package/dist/src/utils/connection.utils.js +48 -0
- package/dist/src/utils/index.d.ts +1 -0
- package/dist/src/utils/index.d.ts.map +1 -1
- package/dist/src/utils/index.js +1 -0
- package/dist/test/astream-reuse.spec.d.ts +2 -0
- package/dist/test/astream-reuse.spec.d.ts.map +1 -0
- package/dist/test/astream-reuse.spec.js +107 -0
- package/dist/test/connection-management.spec.js +1 -0
- package/dist/test/helpers/network-builder.d.ts.map +1 -1
- package/package.json +7 -7
- package/dist/src/connection/o-managed-stream.d.ts +0 -57
- package/dist/src/connection/o-managed-stream.d.ts.map +0 -1
- package/dist/src/connection/o-managed-stream.js +0 -76
- package/dist/test/o-managed-stream.spec.d.ts +0 -2
- package/dist/test/o-managed-stream.spec.d.ts.map +0 -1
- package/dist/test/o-managed-stream.spec.js +0 -122
- package/dist/test/stream-handler-caching.spec.d.ts +0 -2
- package/dist/test/stream-handler-caching.spec.d.ts.map +0 -1
- package/dist/test/stream-handler-caching.spec.js +0 -261
|
@@ -2,6 +2,6 @@ export * from './o-node-connection.js';
|
|
|
2
2
|
export * from './o-node-connection.manager.js';
|
|
3
3
|
export * from './interfaces/o-node-connection.config.js';
|
|
4
4
|
export * from './interfaces/o-node-connection-manager.config.js';
|
|
5
|
-
export * from './o-
|
|
5
|
+
export * from './o-node-connection-stream.js';
|
|
6
6
|
export * from './stream-handler.config.js';
|
|
7
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/connection/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0CAA0C,CAAC;AACzD,cAAc,kDAAkD,CAAC;AACjE,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/connection/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0CAA0C,CAAC;AACzD,cAAc,kDAAkD,CAAC;AACjE,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC"}
|
|
@@ -2,5 +2,5 @@ export * from './o-node-connection.js';
|
|
|
2
2
|
export * from './o-node-connection.manager.js';
|
|
3
3
|
export * from './interfaces/o-node-connection.config.js';
|
|
4
4
|
export * from './interfaces/o-node-connection-manager.config.js';
|
|
5
|
-
export * from './o-
|
|
5
|
+
export * from './o-node-connection-stream.js';
|
|
6
6
|
export * from './stream-handler.config.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { oAddress } from '@olane/o-core';
|
|
2
|
+
import { StreamReusePolicy } from '../stream-handler.config';
|
|
3
|
+
export interface oNodeConnectionStreamConfig {
|
|
4
|
+
direction: 'inbound' | 'outbound';
|
|
5
|
+
reusePolicy: StreamReusePolicy;
|
|
6
|
+
remoteAddress: oAddress;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=o-node-connection-stream.config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"o-node-connection-stream.config.d.ts","sourceRoot":"","sources":["../../../../src/connection/interfaces/o-node-connection-stream.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,MAAM,WAAW,2BAA2B;IAC1C,SAAS,EAAE,SAAS,GAAG,UAAU,CAAC;IAClC,WAAW,EAAE,iBAAiB,CAAC;IAC/B,aAAa,EAAE,QAAQ,CAAC;CACzB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Stream } from '@libp2p/interface';
|
|
2
|
+
import { oObject } from '@olane/o-core';
|
|
3
|
+
import { oNodeConnectionStreamConfig } from './interfaces/o-node-connection-stream.config.js';
|
|
4
|
+
/**
|
|
5
|
+
* oNodeConnectionStream wraps a libp2p Stream with caller/receiver address metadata
|
|
6
|
+
* to enable proper stream reuse based on address pairs rather than protocol only.
|
|
7
|
+
*
|
|
8
|
+
* Key features:
|
|
9
|
+
* - Bidirectional cache keys: A↔B === B↔A
|
|
10
|
+
* - Automatic reusability checking
|
|
11
|
+
* - Idle time tracking for cleanup
|
|
12
|
+
*/
|
|
13
|
+
export declare class oNodeConnectionStream extends oObject {
|
|
14
|
+
readonly p2pStream: Stream;
|
|
15
|
+
readonly config: oNodeConnectionStreamConfig;
|
|
16
|
+
readonly createdAt: number;
|
|
17
|
+
constructor(p2pStream: Stream, config: oNodeConnectionStreamConfig);
|
|
18
|
+
validate(): void;
|
|
19
|
+
/**
|
|
20
|
+
* Checks if the stream is in a valid state:
|
|
21
|
+
* - Stream status is 'open'
|
|
22
|
+
* - Write status is 'writable'
|
|
23
|
+
* - Remote read status is 'readable'
|
|
24
|
+
*
|
|
25
|
+
* @returns true if stream can be used
|
|
26
|
+
*/
|
|
27
|
+
get isValid(): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Gets the age of the stream in milliseconds
|
|
30
|
+
*/
|
|
31
|
+
get age(): number;
|
|
32
|
+
close(): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=o-node-connection-stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"o-node-connection-stream.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-connection-stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAuB,OAAO,EAAiB,MAAM,eAAe,CAAC;AAC5E,OAAO,EAAE,2BAA2B,EAAE,MAAM,iDAAiD,CAAC;AAE9F;;;;;;;;GAQG;AACH,qBAAa,qBAAsB,SAAQ,OAAO;aAI9B,SAAS,EAAE,MAAM;aACjB,MAAM,EAAE,2BAA2B;IAJrD,SAAgB,SAAS,EAAE,MAAM,CAAC;gBAGhB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,2BAA2B;IAOrD,QAAQ;IA6BR;;;;;;;OAOG;IACH,IAAI,OAAO,IAAI,OAAO,CAMrB;IAED;;OAEG;IACH,IAAI,GAAG,IAAI,MAAM,CAEhB;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAgB7B"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { oError, oErrorCodes, oObject } from '@olane/o-core';
|
|
2
|
+
/**
|
|
3
|
+
* oNodeConnectionStream wraps a libp2p Stream with caller/receiver address metadata
|
|
4
|
+
* to enable proper stream reuse based on address pairs rather than protocol only.
|
|
5
|
+
*
|
|
6
|
+
* Key features:
|
|
7
|
+
* - Bidirectional cache keys: A↔B === B↔A
|
|
8
|
+
* - Automatic reusability checking
|
|
9
|
+
* - Idle time tracking for cleanup
|
|
10
|
+
*/
|
|
11
|
+
export class oNodeConnectionStream extends oObject {
|
|
12
|
+
constructor(p2pStream, config) {
|
|
13
|
+
super();
|
|
14
|
+
this.p2pStream = p2pStream;
|
|
15
|
+
this.config = config;
|
|
16
|
+
this.createdAt = Date.now();
|
|
17
|
+
}
|
|
18
|
+
// callable pattern to disrupt flow if not in valid state
|
|
19
|
+
validate() {
|
|
20
|
+
// do nothing
|
|
21
|
+
if (!this.p2pStream ||
|
|
22
|
+
(this.p2pStream.status !== 'open' && this.p2pStream.status !== 'reset')) {
|
|
23
|
+
throw new oError(oErrorCodes.FAILED_TO_DIAL_TARGET, 'Failed to dial target');
|
|
24
|
+
}
|
|
25
|
+
if (this.p2pStream.status === 'reset') {
|
|
26
|
+
this.logger.debug('P2P stream failed to create, status:', this.p2pStream.status);
|
|
27
|
+
throw new oError(oErrorCodes.CONNECTION_LIMIT_REACHED, 'Connection limit reached or configuration prevented stream creation');
|
|
28
|
+
}
|
|
29
|
+
if (!this.isValid) {
|
|
30
|
+
throw new oError(oErrorCodes.INVALID_STATE, 'Session is not in a valid state');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Checks if the stream is in a valid state:
|
|
35
|
+
* - Stream status is 'open'
|
|
36
|
+
* - Write status is 'writable'
|
|
37
|
+
* - Remote read status is 'readable'
|
|
38
|
+
*
|
|
39
|
+
* @returns true if stream can be used
|
|
40
|
+
*/
|
|
41
|
+
get isValid() {
|
|
42
|
+
return (this.p2pStream.status === 'open' &&
|
|
43
|
+
this.p2pStream.writeStatus === 'writable' &&
|
|
44
|
+
this.p2pStream.remoteReadStatus === 'readable');
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Gets the age of the stream in milliseconds
|
|
48
|
+
*/
|
|
49
|
+
get age() {
|
|
50
|
+
return Date.now() - this.createdAt;
|
|
51
|
+
}
|
|
52
|
+
async close() {
|
|
53
|
+
// Don't close if reuse policy is enabled
|
|
54
|
+
if (this.config.reusePolicy === 'reuse') {
|
|
55
|
+
this.logger.debug('Stream reuse enabled, not closing stream');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (this.p2pStream.status === 'open') {
|
|
59
|
+
try {
|
|
60
|
+
// force the close for now until we can implement a proper close
|
|
61
|
+
await this.p2pStream.abort(new Error('Stream closed'));
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
this.logger.debug('Error closing stream:', error.message);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -1,18 +1,24 @@
|
|
|
1
|
-
import { Connection
|
|
1
|
+
import { Connection } from '@olane/o-config';
|
|
2
2
|
import { oConnection, oRequest, oResponse } from '@olane/o-core';
|
|
3
3
|
import { oNodeConnectionConfig } from './interfaces/o-node-connection.config.js';
|
|
4
4
|
import { StreamHandler } from './stream-handler.js';
|
|
5
5
|
import type { StreamReusePolicy } from './stream-handler.config.js';
|
|
6
|
+
import { oNodeAddress } from '../router/o-node.address.js';
|
|
7
|
+
import { oNodeConnectionStream } from './o-node-connection-stream.js';
|
|
6
8
|
export declare class oNodeConnection extends oConnection {
|
|
7
9
|
protected readonly config: oNodeConnectionConfig;
|
|
8
10
|
p2pConnection: Connection;
|
|
9
11
|
protected streamHandler: StreamHandler;
|
|
10
12
|
protected reusePolicy: StreamReusePolicy;
|
|
11
13
|
constructor(config: oNodeConnectionConfig);
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
get remotePeerId(): import("@olane/o-config").PeerId;
|
|
15
|
+
get remoteAddr(): import("@olane/o-config").Multiaddr;
|
|
16
|
+
supportsAddress(address: oNodeAddress): boolean;
|
|
17
|
+
getOrCreateStream(): Promise<oNodeConnectionStream>;
|
|
18
|
+
createStream(): Promise<oNodeConnectionStream>;
|
|
19
|
+
get streams(): oNodeConnectionStream[];
|
|
14
20
|
transmit(request: oRequest): Promise<oResponse>;
|
|
15
|
-
postTransmit(stream:
|
|
21
|
+
postTransmit(stream: oNodeConnectionStream): Promise<void>;
|
|
16
22
|
abort(error: Error): Promise<void>;
|
|
17
23
|
close(): Promise<void>;
|
|
18
24
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"o-node-connection.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,
|
|
1
|
+
{"version":3,"file":"o-node-connection.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAU,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAEL,WAAW,EAGX,QAAQ,EACR,SAAS,EACV,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAEV,iBAAiB,EAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAGtE,qBAAa,eAAgB,SAAQ,WAAW;IAKlC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,qBAAqB;IAJrD,aAAa,EAAE,UAAU,CAAC;IACjC,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC;IACvC,SAAS,CAAC,WAAW,EAAE,iBAAiB,CAAC;gBAEV,MAAM,EAAE,qBAAqB;IAO5D,IAAI,YAAY,qCAEf;IAED,IAAI,UAAU,wCAEb;IAED,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO;IAMzC,iBAAiB,IAAI,OAAO,CAAC,qBAAqB,CAAC;IAanD,YAAY,IAAI,OAAO,CAAC,qBAAqB,CAAC;IA6BpD,IAAI,OAAO,IAAI,qBAAqB,EAAE,CAcrC;IAEK,QAAQ,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IA6C/C,YAAY,CAAC,MAAM,EAAE,qBAAqB;IAI1C,KAAK,CAAC,KAAK,EAAE,KAAK;IAMlB,KAAK;CAKZ"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { oConnection, oError, oErrorCodes, } from '@olane/o-core';
|
|
2
2
|
import { StreamHandler } from './stream-handler.js';
|
|
3
|
+
import { oNodeConnectionStream } from './o-node-connection-stream.js';
|
|
3
4
|
export class oNodeConnection extends oConnection {
|
|
4
5
|
constructor(config) {
|
|
5
6
|
super(config);
|
|
@@ -8,45 +9,64 @@ export class oNodeConnection extends oConnection {
|
|
|
8
9
|
this.streamHandler = new StreamHandler(this.logger);
|
|
9
10
|
this.reusePolicy = config.reusePolicy ?? 'none';
|
|
10
11
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
12
|
+
get remotePeerId() {
|
|
13
|
+
return this.p2pConnection.remotePeer;
|
|
14
|
+
}
|
|
15
|
+
get remoteAddr() {
|
|
16
|
+
return this.p2pConnection.remoteAddr;
|
|
17
|
+
}
|
|
18
|
+
supportsAddress(address) {
|
|
19
|
+
return address.libp2pTransports.some((transport) => {
|
|
20
|
+
return transport.toString() === this.remoteAddr.toString();
|
|
21
|
+
});
|
|
22
22
|
}
|
|
23
23
|
async getOrCreateStream() {
|
|
24
|
-
|
|
24
|
+
if (this.reusePolicy === 'reuse' && this.streams.length > 0) {
|
|
25
|
+
this.logger.debug('Returning reuse stream: ', this.streams[0].p2pStream.protocol);
|
|
26
|
+
// search for streams that allow re-use
|
|
27
|
+
return this.streams[0];
|
|
28
|
+
}
|
|
29
|
+
return this.createStream();
|
|
30
|
+
}
|
|
31
|
+
async createStream() {
|
|
32
|
+
const protocol = this.nextHopAddress.protocol +
|
|
33
|
+
(this.reusePolicy === 'reuse' ? '/reuse' : ''); // connect specifically to the reuse protocol version if desired
|
|
34
|
+
this.logger.debug('Creating stream for protocol:', protocol);
|
|
35
|
+
const stream = await this.p2pConnection.newStream(protocol, {
|
|
25
36
|
signal: this.abortSignal,
|
|
26
37
|
maxOutboundStreams: process.env.MAX_OUTBOUND_STREAMS
|
|
27
38
|
? parseInt(process.env.MAX_OUTBOUND_STREAMS)
|
|
28
39
|
: 1000,
|
|
29
40
|
runOnLimitedConnection: this.config.runOnLimitedConnection ?? true,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
});
|
|
42
|
+
const managedStream = new oNodeConnectionStream(stream, {
|
|
43
|
+
direction: stream.direction,
|
|
44
|
+
reusePolicy: this.config.reusePolicy ?? 'none', // default to no re-use stream
|
|
45
|
+
remoteAddress: this.nextHopAddress,
|
|
46
|
+
});
|
|
47
|
+
// print the num streams
|
|
48
|
+
const numStreams = this.streams.map((s) => s.isValid).length;
|
|
49
|
+
this.logger.debug(`Connection spawned new stream: ${stream.id}. Connection now has ${numStreams} total streams open`);
|
|
50
|
+
return managedStream;
|
|
51
|
+
}
|
|
52
|
+
get streams() {
|
|
53
|
+
return (this.p2pConnection?.streams
|
|
54
|
+
?.filter((s) => {
|
|
55
|
+
return s.protocol.includes('/o/');
|
|
56
|
+
})
|
|
57
|
+
.map((s) => {
|
|
58
|
+
return new oNodeConnectionStream(s, {
|
|
59
|
+
direction: s.direction,
|
|
60
|
+
reusePolicy: this.config.reusePolicy ?? 'none', // default to no re-use stream
|
|
61
|
+
remoteAddress: this.nextHopAddress,
|
|
62
|
+
});
|
|
63
|
+
}) || []);
|
|
42
64
|
}
|
|
43
65
|
async transmit(request) {
|
|
44
66
|
try {
|
|
45
|
-
// if (this.config.runOnLimitedConnection) {
|
|
46
|
-
// this.logger.debug('Running on limited connection...');
|
|
47
|
-
// }
|
|
48
67
|
const stream = await this.getOrCreateStream();
|
|
49
|
-
|
|
68
|
+
// ensure stream is valid
|
|
69
|
+
stream.validate();
|
|
50
70
|
const streamConfig = {
|
|
51
71
|
signal: this.abortSignal,
|
|
52
72
|
drainTimeoutMs: this.config.drainTimeoutMs,
|
|
@@ -54,11 +74,11 @@ export class oNodeConnection extends oConnection {
|
|
|
54
74
|
};
|
|
55
75
|
// Send the request with backpressure handling
|
|
56
76
|
const data = new TextEncoder().encode(request.toString());
|
|
57
|
-
await this.streamHandler.sendLengthPrefixed(stream, data, streamConfig);
|
|
77
|
+
await this.streamHandler.sendLengthPrefixed(stream.p2pStream, data, streamConfig);
|
|
58
78
|
// Handle response using StreamHandler
|
|
59
79
|
// Pass request handler if configured to enable bidirectional stream processing
|
|
60
80
|
// Pass request ID to enable proper response correlation on shared streams
|
|
61
|
-
const response = await this.streamHandler.handleOutgoingStream(stream, this.emitter, streamConfig, this.config.requestHandler, request.id);
|
|
81
|
+
const response = await this.streamHandler.handleOutgoingStream(stream.p2pStream, this.emitter, streamConfig, this.config.requestHandler, request.id);
|
|
62
82
|
// Handle cleanup of the stream
|
|
63
83
|
await this.postTransmit(stream);
|
|
64
84
|
return response;
|
|
@@ -71,10 +91,7 @@ export class oNodeConnection extends oConnection {
|
|
|
71
91
|
}
|
|
72
92
|
}
|
|
73
93
|
async postTransmit(stream) {
|
|
74
|
-
|
|
75
|
-
reusePolicy: this.reusePolicy,
|
|
76
|
-
};
|
|
77
|
-
await this.streamHandler.close(stream, streamConfig);
|
|
94
|
+
await stream.close();
|
|
78
95
|
}
|
|
79
96
|
async abort(error) {
|
|
80
97
|
this.logger.debug('Aborting connection');
|
|
@@ -30,6 +30,10 @@ export declare class oNodeConnectionManager extends oConnectionManager {
|
|
|
30
30
|
private getPeerIdFromAddress;
|
|
31
31
|
getOrCreateConnection(nextHopAddress: oAddress, address: oAddress): Promise<Connection>;
|
|
32
32
|
private performDial;
|
|
33
|
+
answer(config: oConnectionConfig & {
|
|
34
|
+
p2pConnection: Connection;
|
|
35
|
+
reuse?: boolean;
|
|
36
|
+
}): Promise<oNodeConnection>;
|
|
33
37
|
/**
|
|
34
38
|
* Connect to a given address, reusing libp2p connections when possible
|
|
35
39
|
* @param config - Connection configuration
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"o-node-connection.manager.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-connection.manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,MAAM,EAAE,UAAU,EAAU,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,4BAA4B,EAAE,MAAM,kDAAkD,CAAC;AAEhG,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,qBAAa,sBAAuB,SAAQ,kBAAkB;IAQhD,QAAQ,CAAC,MAAM,EAAE,4BAA4B;IAPzD,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,oBAAoB,CAAC,CAAS;IACtC,OAAO,CAAC,qBAAqB,CAAC,CAAS;IACvC,OAAO,CAAC,yBAAyB,CAAsC;IACvE,OAAO,CAAC,0BAA0B,CACtB;gBAES,MAAM,EAAE,4BAA4B;IAWzD;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAsBhC;;;;;;OAMG;IACH,OAAO,CAAC,0BAA0B;IAiBlC;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAatB,qBAAqB,CACzB,cAAc,EAAE,QAAQ,EACxB,OAAO,EAAE,QAAQ,GAChB,OAAO,CAAC,UAAU,CAAC;YA+DR,WAAW;
|
|
1
|
+
{"version":3,"file":"o-node-connection.manager.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-connection.manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAChF,OAAO,EAAE,MAAM,EAAE,UAAU,EAAU,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,4BAA4B,EAAE,MAAM,kDAAkD,CAAC;AAEhG,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,qBAAa,sBAAuB,SAAQ,kBAAkB;IAQhD,QAAQ,CAAC,MAAM,EAAE,4BAA4B;IAPzD,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,oBAAoB,CAAC,CAAS;IACtC,OAAO,CAAC,qBAAqB,CAAC,CAAS;IACvC,OAAO,CAAC,yBAAyB,CAAsC;IACvE,OAAO,CAAC,0BAA0B,CACtB;gBAES,MAAM,EAAE,4BAA4B;IAWzD;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAsBhC;;;;;;OAMG;IACH,OAAO,CAAC,0BAA0B;IAiBlC;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAatB,qBAAqB,CACzB,cAAc,EAAE,QAAQ,EACxB,OAAO,EAAE,QAAQ,GAChB,OAAO,CAAC,UAAU,CAAC;YA+DR,WAAW;IAwBnB,MAAM,CACV,MAAM,EAAE,iBAAiB,GAAG;QAAE,aAAa,EAAE,UAAU,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GACzE,OAAO,CAAC,eAAe,CAAC;IAmC3B;;;;OAIG;IACG,OAAO,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,eAAe,CAAC;IA8BlE;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO;IAwCpC;;;;OAIG;IACH,yBAAyB,CAAC,OAAO,EAAE,QAAQ,GAAG,UAAU,GAAG,IAAI;IA+C/D;;;OAGG;IACH,aAAa,IAAI;QACf,iBAAiB,EAAE,MAAM,CAAC;QAC1B,YAAY,EAAE,MAAM,CAAC;QACrB,iBAAiB,EAAE,KAAK,CAAC;YAAE,MAAM,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAC9D;IAaD;;;OAGG;IACH,uBAAuB,IAAI,MAAM;CAgBlC"}
|
|
@@ -130,6 +130,30 @@ export class oNodeConnectionManager extends oConnectionManager {
|
|
|
130
130
|
});
|
|
131
131
|
return connection;
|
|
132
132
|
}
|
|
133
|
+
async answer(config) {
|
|
134
|
+
const { address, nextHopAddress, callerAddress, readTimeoutMs, drainTimeoutMs, p2pConnection, reuse, } = config;
|
|
135
|
+
const connection = new oNodeConnection({
|
|
136
|
+
nextHopAddress: nextHopAddress,
|
|
137
|
+
address: address,
|
|
138
|
+
p2pConnection: p2pConnection,
|
|
139
|
+
callerAddress: callerAddress,
|
|
140
|
+
readTimeoutMs: readTimeoutMs ?? this.defaultReadTimeoutMs,
|
|
141
|
+
drainTimeoutMs: drainTimeoutMs ?? this.defaultDrainTimeoutMs,
|
|
142
|
+
isStream: config.isStream ?? false,
|
|
143
|
+
abortSignal: config.abortSignal,
|
|
144
|
+
runOnLimitedConnection: this.config.runOnLimitedConnection ?? false,
|
|
145
|
+
requestHandler: config.requestHandler ?? undefined,
|
|
146
|
+
reusePolicy: reuse ? 'reuse' : 'none',
|
|
147
|
+
});
|
|
148
|
+
const transportKey = this.getTransportKeyFromAddress(nextHopAddress);
|
|
149
|
+
if (transportKey) {
|
|
150
|
+
this.connectionsByTransportKey.set(transportKey, p2pConnection);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
this.logger.error('Should not happen! Failed to generate a transport key for address:', nextHopAddress);
|
|
154
|
+
}
|
|
155
|
+
return connection;
|
|
156
|
+
}
|
|
133
157
|
/**
|
|
134
158
|
* Connect to a given address, reusing libp2p connections when possible
|
|
135
159
|
* @param config - Connection configuration
|
|
@@ -4,9 +4,8 @@ import { EventEmitter } from 'events';
|
|
|
4
4
|
import { oRequest, oResponse, Logger } from '@olane/o-core';
|
|
5
5
|
import type { oRouterRequest } from '@olane/o-core';
|
|
6
6
|
import type { oConnection } from '@olane/o-core';
|
|
7
|
-
import type { oAddress } from '@olane/o-core';
|
|
8
7
|
import type { RunResult } from '@olane/o-tool';
|
|
9
|
-
import type { StreamHandlerConfig
|
|
8
|
+
import type { StreamHandlerConfig } from './stream-handler.config.js';
|
|
10
9
|
/**
|
|
11
10
|
* StreamHandler centralizes all stream-related functionality including:
|
|
12
11
|
* - Message type detection (request vs response)
|
|
@@ -17,7 +16,6 @@ import type { StreamHandlerConfig, StreamReusePolicy } from './stream-handler.co
|
|
|
17
16
|
*/
|
|
18
17
|
export declare class StreamHandler {
|
|
19
18
|
private logger;
|
|
20
|
-
private streamCache;
|
|
21
19
|
constructor(logger?: Logger);
|
|
22
20
|
/**
|
|
23
21
|
* Detects if a decoded message is a request
|
|
@@ -51,55 +49,6 @@ export declare class StreamHandler {
|
|
|
51
49
|
* @returns Cache key string
|
|
52
50
|
*/
|
|
53
51
|
private buildCacheKey;
|
|
54
|
-
/**
|
|
55
|
-
* Caches a managed stream for reuse
|
|
56
|
-
*
|
|
57
|
-
* @param managedStream - The managed stream to cache
|
|
58
|
-
*/
|
|
59
|
-
private cacheStream;
|
|
60
|
-
/**
|
|
61
|
-
* Removes a stream from the cache
|
|
62
|
-
*
|
|
63
|
-
* @param stream - The stream to remove
|
|
64
|
-
*/
|
|
65
|
-
private removeStreamFromCache;
|
|
66
|
-
/**
|
|
67
|
-
* Sets up cleanup listener for stream close events
|
|
68
|
-
*
|
|
69
|
-
* @param stream - The stream to monitor
|
|
70
|
-
*/
|
|
71
|
-
private setupStreamCleanup;
|
|
72
|
-
/**
|
|
73
|
-
* Extracts the remote peer's address from a connection
|
|
74
|
-
* Falls back to creating an address from the peer ID if no address metadata is available
|
|
75
|
-
*
|
|
76
|
-
* @param connection - The libp2p connection
|
|
77
|
-
* @returns The remote peer's oAddress
|
|
78
|
-
*/
|
|
79
|
-
extractRemotePeerAddress(connection: Connection): oAddress;
|
|
80
|
-
/**
|
|
81
|
-
* Caches an inbound stream for bidirectional reuse
|
|
82
|
-
* This allows the same stream to be reused for responses
|
|
83
|
-
*
|
|
84
|
-
* @param stream - The inbound stream to cache
|
|
85
|
-
* @param callerAddress - The address of the caller
|
|
86
|
-
* @param receiverAddress - The address of the receiver (local node)
|
|
87
|
-
* @param reusePolicy - Whether to enable caching
|
|
88
|
-
*/
|
|
89
|
-
cacheInboundStream(stream: Stream, callerAddress: oAddress, receiverAddress: oAddress, reusePolicy?: StreamReusePolicy): void;
|
|
90
|
-
/**
|
|
91
|
-
* Gets an existing open stream or creates a new one based on reuse policy
|
|
92
|
-
*
|
|
93
|
-
* @param connection - The libp2p connection
|
|
94
|
-
* @param protocol - The protocol to use for the stream
|
|
95
|
-
* @param config - Stream handler configuration
|
|
96
|
-
* @param streamAddresses - Optional addresses for address-based stream reuse
|
|
97
|
-
*/
|
|
98
|
-
getOrCreateStream(connection: Connection, protocol: string, config?: StreamHandlerConfig, streamAddresses?: {
|
|
99
|
-
callerAddress: oAddress;
|
|
100
|
-
receiverAddress: oAddress;
|
|
101
|
-
direction: 'inbound' | 'outbound';
|
|
102
|
-
}): Promise<Stream>;
|
|
103
52
|
/**
|
|
104
53
|
* Sends data through a stream using length-prefixed encoding (libp2p v3 best practice)
|
|
105
54
|
* Each message is automatically prefixed with a varint indicating the message length
|
|
@@ -110,13 +59,6 @@ export declare class StreamHandler {
|
|
|
110
59
|
* @param config - Configuration for timeout and other options
|
|
111
60
|
*/
|
|
112
61
|
sendLengthPrefixed(stream: Stream, data: Uint8Array, config?: StreamHandlerConfig): Promise<void>;
|
|
113
|
-
/**
|
|
114
|
-
* Closes a stream safely with error handling
|
|
115
|
-
*
|
|
116
|
-
* @param stream - The stream to close
|
|
117
|
-
* @param config - Configuration including reuse policy
|
|
118
|
-
*/
|
|
119
|
-
close(stream: Stream, config?: StreamHandlerConfig): Promise<void>;
|
|
120
62
|
/**
|
|
121
63
|
* Handles an incoming stream on the server side using length-prefixed protocol
|
|
122
64
|
* Uses async read loops instead of event listeners (libp2p v3 best practice)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream-handler.d.ts","sourceRoot":"","sources":["../../../src/connection/stream-handler.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EACL,QAAQ,EACR,SAAS,EAIT,MAAM,EAEP,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"stream-handler.d.ts","sourceRoot":"","sources":["../../../src/connection/stream-handler.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EACL,QAAQ,EACR,SAAS,EAIT,MAAM,EAEP,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,KAAK,EACV,mBAAmB,EAEpB,MAAM,4BAA4B,CAAC;AAKpC;;;;;;;GAOG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,CAAC,EAAE,MAAM;IAI3B;;;OAGG;IACH,SAAS,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO;IAIhC;;;OAGG;IACH,UAAU,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO;IAIjC;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,mBAAmB;IAqC3B;;;;;;;OAOG;IACH,OAAO,CAAC,aAAa;IA0HrB;;;;;;;;OAQG;IACG,kBAAkB,CACtB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,UAAU,EAChB,MAAM,GAAE,mBAAwB,GAC/B,OAAO,CAAC,IAAI,CAAC;IAKhB;;;;;;;;OAQG;IACG,oBAAoB,CACxB,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,EACtB,YAAY,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,GACtE,OAAO,CAAC,IAAI,CAAC;IA+BhB;;;;;;OAMG;YACW,oBAAoB;IA6BlC;;;;;;;;;;OAUG;IACG,oBAAoB,CACxB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,YAAY,EACrB,MAAM,GAAE,mBAAwB,EAChC,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,CAAC,EAC1E,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAC1B,OAAO,CAAC,SAAS,CAAC;IAiErB;;;;;;;OAOG;IACG,cAAc,CAClB,OAAO,EAAE,cAAc,EACvB,cAAc,EAAE,MAAM,EACtB,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,GAChD,OAAO,CAAC,IAAI,CAAC;CAyBjB"}
|