@olane/o-node 0.7.53 → 0.7.55
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/interfaces/o-node-connection.config.d.ts +2 -1
- package/dist/src/connection/interfaces/o-node-connection.config.d.ts.map +1 -1
- package/dist/src/connection/interfaces/stream-init-message.d.ts +39 -4
- package/dist/src/connection/interfaces/stream-init-message.d.ts.map +1 -1
- package/dist/src/connection/interfaces/stream-init-message.js +11 -1
- package/dist/src/connection/o-node-connection.d.ts +49 -3
- package/dist/src/connection/o-node-connection.d.ts.map +1 -1
- package/dist/src/connection/o-node-connection.js +120 -2
- package/dist/src/connection/o-node-connection.manager.d.ts +6 -55
- package/dist/src/connection/o-node-connection.manager.d.ts.map +1 -1
- package/dist/src/connection/o-node-connection.manager.js +47 -183
- package/dist/src/connection/o-node-stream.d.ts.map +1 -1
- package/dist/src/connection/o-node-stream.js +1 -0
- package/dist/src/connection/o-node-stream.manager.d.ts +34 -5
- package/dist/src/connection/o-node-stream.manager.d.ts.map +1 -1
- package/dist/src/connection/o-node-stream.manager.js +190 -20
- package/dist/src/connection/stream-manager.events.d.ts +13 -1
- package/dist/src/connection/stream-manager.events.d.ts.map +1 -1
- package/dist/src/connection/stream-manager.events.js +2 -0
- package/dist/src/o-node.tool.d.ts.map +1 -1
- package/dist/src/o-node.tool.js +14 -19
- package/dist/src/utils/connection.utils.d.ts +3 -3
- package/dist/src/utils/connection.utils.d.ts.map +1 -1
- package/dist/src/utils/connection.utils.js +46 -19
- package/package.json +7 -7
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { Connection } from '@olane/o-config';
|
|
1
|
+
import { Connection, Libp2p } from '@olane/o-config';
|
|
2
2
|
import { oConnectionConfig } from '@olane/o-core';
|
|
3
3
|
import type { StreamReusePolicy } from '../stream-handler.config.js';
|
|
4
4
|
export interface oNodeConnectionConfig extends oConnectionConfig {
|
|
5
5
|
p2pConnection: Connection;
|
|
6
|
+
p2pNode?: Libp2p;
|
|
6
7
|
runOnLimitedConnection?: boolean;
|
|
7
8
|
reusePolicy?: StreamReusePolicy;
|
|
8
9
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"o-node-connection.config.d.ts","sourceRoot":"","sources":["../../../../src/connection/interfaces/o-node-connection.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"o-node-connection.config.d.ts","sourceRoot":"","sources":["../../../../src/connection/interfaces/o-node-connection.config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAErE,MAAM,WAAW,qBAAsB,SAAQ,iBAAiB;IAC9D,aAAa,EAAE,UAAU,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,WAAW,CAAC,EAAE,iBAAiB,CAAC;CACjC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Message sent by limited connection clients to identify their dedicated
|
|
3
|
-
* This allows the receiver to identify which
|
|
2
|
+
* Message sent by limited connection clients to identify their dedicated persistent streams
|
|
3
|
+
* This allows the receiver to identify which streams to use for bidirectional communication
|
|
4
4
|
*/
|
|
5
5
|
export interface StreamInitMessage {
|
|
6
6
|
/**
|
|
@@ -9,10 +9,11 @@ export interface StreamInitMessage {
|
|
|
9
9
|
type: 'stream-init';
|
|
10
10
|
/**
|
|
11
11
|
* Role of this stream
|
|
12
|
-
* - 'reader': Dedicated reader stream for receiving requests
|
|
12
|
+
* - 'reader': Dedicated reader stream for receiving requests from receiver
|
|
13
|
+
* - 'writer': Dedicated writer stream for sending responses back to receiver
|
|
13
14
|
* - 'standard': Standard request-response stream
|
|
14
15
|
*/
|
|
15
|
-
role: 'reader' | 'standard';
|
|
16
|
+
role: 'reader' | 'writer' | 'standard';
|
|
16
17
|
/**
|
|
17
18
|
* Timestamp when the stream was created
|
|
18
19
|
*/
|
|
@@ -26,4 +27,38 @@ export interface StreamInitMessage {
|
|
|
26
27
|
* Type guard to check if a message is a StreamInitMessage
|
|
27
28
|
*/
|
|
28
29
|
export declare function isStreamInitMessage(message: any): message is StreamInitMessage;
|
|
30
|
+
/**
|
|
31
|
+
* Acknowledgment message sent by receiver in response to stream-init
|
|
32
|
+
* This confirms that the receiver has processed and registered the stream
|
|
33
|
+
*/
|
|
34
|
+
export interface StreamInitAckMessage {
|
|
35
|
+
/**
|
|
36
|
+
* Message type identifier
|
|
37
|
+
*/
|
|
38
|
+
type: 'stream-init-ack';
|
|
39
|
+
/**
|
|
40
|
+
* Status of the initialization
|
|
41
|
+
*/
|
|
42
|
+
status: 'success' | 'error';
|
|
43
|
+
/**
|
|
44
|
+
* The stream ID that was registered
|
|
45
|
+
*/
|
|
46
|
+
streamId: string;
|
|
47
|
+
/**
|
|
48
|
+
* The role that was registered
|
|
49
|
+
*/
|
|
50
|
+
role: 'reader' | 'writer' | 'standard';
|
|
51
|
+
/**
|
|
52
|
+
* Optional error message if status is 'error'
|
|
53
|
+
*/
|
|
54
|
+
error?: string;
|
|
55
|
+
/**
|
|
56
|
+
* Timestamp when the ack was sent
|
|
57
|
+
*/
|
|
58
|
+
timestamp: number;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Type guard to check if a message is a StreamInitAckMessage
|
|
62
|
+
*/
|
|
63
|
+
export declare function isStreamInitAckMessage(message: any): message is StreamInitAckMessage;
|
|
29
64
|
//# sourceMappingURL=stream-init-message.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream-init-message.d.ts","sourceRoot":"","sources":["../../../../src/connection/interfaces/stream-init-message.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,IAAI,EAAE,aAAa,CAAC;IAEpB
|
|
1
|
+
{"version":3,"file":"stream-init-message.d.ts","sourceRoot":"","sources":["../../../../src/connection/interfaces/stream-init-message.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,IAAI,EAAE,aAAa,CAAC;IAEpB;;;;;OAKG;IACH,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;IAEvC;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,IAAI,iBAAiB,CAM9E;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,IAAI,EAAE,iBAAiB,CAAC;IAExB;;OAEG;IACH,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC;IAE5B;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;IAEvC;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,GAAG,GACX,OAAO,IAAI,oBAAoB,CAQjC"}
|
|
@@ -3,6 +3,16 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export function isStreamInitMessage(message) {
|
|
5
5
|
return (message?.type === 'stream-init' &&
|
|
6
|
-
(message.role === 'reader' || message.role === 'standard') &&
|
|
6
|
+
(message.role === 'reader' || message.role === 'writer' || message.role === 'standard') &&
|
|
7
|
+
typeof message.timestamp === 'number');
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Type guard to check if a message is a StreamInitAckMessage
|
|
11
|
+
*/
|
|
12
|
+
export function isStreamInitAckMessage(message) {
|
|
13
|
+
return (message?.type === 'stream-init-ack' &&
|
|
14
|
+
(message.status === 'success' || message.status === 'error') &&
|
|
15
|
+
typeof message.streamId === 'string' &&
|
|
16
|
+
(message.role === 'reader' || message.role === 'writer' || message.role === 'standard') &&
|
|
7
17
|
typeof message.timestamp === 'number');
|
|
8
18
|
}
|
|
@@ -1,27 +1,73 @@
|
|
|
1
|
-
import { Connection } from '@olane/o-config';
|
|
2
|
-
import { oConnection, oRequest, oResponse } from '@olane/o-core';
|
|
1
|
+
import { Connection, Libp2p, Multiaddr } from '@olane/o-config';
|
|
2
|
+
import { oAddress, oConnection, oRequest, oResponse } from '@olane/o-core';
|
|
3
3
|
import { oNodeConnectionConfig } from './interfaces/o-node-connection.config.js';
|
|
4
4
|
import type { StreamReusePolicy } from './stream-handler.config.js';
|
|
5
5
|
import { oNodeAddress } from '../router/o-node.address.js';
|
|
6
6
|
import { oNodeStream } from './o-node-stream.js';
|
|
7
7
|
import { oNodeStreamManager } from './o-node-stream.manager.js';
|
|
8
|
+
interface CachedIdentifyData {
|
|
9
|
+
protocols: string[];
|
|
10
|
+
agentVersion?: string;
|
|
11
|
+
protocolVersion?: string;
|
|
12
|
+
listenAddrs: Multiaddr[];
|
|
13
|
+
observedAddr?: Multiaddr;
|
|
14
|
+
timestamp: number;
|
|
15
|
+
}
|
|
8
16
|
export declare class oNodeConnection extends oConnection {
|
|
9
17
|
protected readonly config: oNodeConnectionConfig;
|
|
10
18
|
p2pConnection: Connection;
|
|
11
19
|
protected reusePolicy: StreamReusePolicy;
|
|
12
20
|
streamManager: oNodeStreamManager;
|
|
21
|
+
protected p2pNode?: Libp2p;
|
|
22
|
+
protected identifyData?: CachedIdentifyData;
|
|
23
|
+
protected identifyListener?: (evt: any) => void;
|
|
13
24
|
constructor(config: oNodeConnectionConfig);
|
|
14
25
|
get remotePeerId(): import("@olane/o-config").PeerId;
|
|
15
|
-
get remoteAddr():
|
|
26
|
+
get remoteAddr(): Multiaddr;
|
|
16
27
|
/**
|
|
17
28
|
* Get the connection configuration for compatibility checking.
|
|
18
29
|
*/
|
|
19
30
|
get connectionConfig(): oNodeConnectionConfig;
|
|
20
31
|
supportsAddress(address: oNodeAddress): boolean;
|
|
21
32
|
get streams(): oNodeStream[];
|
|
33
|
+
/**
|
|
34
|
+
* Get cached identify data for the remote peer.
|
|
35
|
+
* Returns undefined if identify event hasn't been received yet.
|
|
36
|
+
*/
|
|
37
|
+
get cachedIdentifyData(): CachedIdentifyData | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* Get protocols supported by the remote peer from cached identify data.
|
|
40
|
+
* Returns empty array if identify data not available yet.
|
|
41
|
+
*/
|
|
42
|
+
get remoteProtocols(): string[];
|
|
43
|
+
/**
|
|
44
|
+
* Get agent version of the remote peer from cached identify data.
|
|
45
|
+
*/
|
|
46
|
+
get remoteAgentVersion(): string | undefined;
|
|
47
|
+
/**
|
|
48
|
+
* Get protocol version of the remote peer from cached identify data.
|
|
49
|
+
*/
|
|
50
|
+
get remoteProtocolVersion(): string | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Get listen addresses advertised by the remote peer.
|
|
53
|
+
* Returns empty array if identify data not available yet.
|
|
54
|
+
*/
|
|
55
|
+
get remoteListenAddrs(): Multiaddr[];
|
|
56
|
+
/**
|
|
57
|
+
* Get our observed address as seen by the remote peer.
|
|
58
|
+
*/
|
|
59
|
+
get observedAddress(): Multiaddr | undefined;
|
|
60
|
+
get address(): oAddress;
|
|
61
|
+
get nextHopAddress(): oAddress;
|
|
62
|
+
get callerAddress(): oAddress | undefined;
|
|
22
63
|
transmit(request: oRequest): Promise<oResponse>;
|
|
23
64
|
postTransmit(stream: oNodeStream): Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
* Set up persistent listener for identify events from the remote peer
|
|
67
|
+
*/
|
|
68
|
+
protected setupIdentifyListener(): void;
|
|
24
69
|
abort(error: Error): Promise<void>;
|
|
25
70
|
close(): Promise<void>;
|
|
26
71
|
}
|
|
72
|
+
export {};
|
|
27
73
|
//# sourceMappingURL=o-node-connection.d.ts.map
|
|
@@ -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,EAAU,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"o-node-connection.d.ts","sourceRoot":"","sources":["../../../src/connection/o-node-connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAU,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAEL,QAAQ,EACR,WAAW,EAGX,QAAQ,EACR,SAAS,EACV,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,qBAAqB,EAAE,MAAM,0CAA0C,CAAC;AACjF,OAAO,KAAK,EAEV,iBAAiB,EAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,UAAU,kBAAkB;IAC1B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,SAAS,EAAE,CAAC;IACzB,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,eAAgB,SAAQ,WAAW;IAQlC,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,qBAAqB;IAPrD,aAAa,EAAE,UAAU,CAAC;IACjC,SAAS,CAAC,WAAW,EAAE,iBAAiB,CAAC;IAClC,aAAa,EAAE,kBAAkB,CAAC;IACzC,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAC5C,SAAS,CAAC,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;gBAEjB,MAAM,EAAE,qBAAqB;IAe5D,IAAI,YAAY,qCAEf;IAED,IAAI,UAAU,cAEb;IAED;;OAEG;IACH,IAAI,gBAAgB,IAAI,qBAAqB,CAE5C;IAED,eAAe,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO;IAM/C,IAAI,OAAO,IAAI,WAAW,EAAE,CAE3B;IAED;;;OAGG;IACH,IAAI,kBAAkB,IAAI,kBAAkB,GAAG,SAAS,CAEvD;IAED;;;OAGG;IACH,IAAI,eAAe,IAAI,MAAM,EAAE,CAE9B;IAED;;OAEG;IACH,IAAI,kBAAkB,IAAI,MAAM,GAAG,SAAS,CAE3C;IAED;;OAEG;IACH,IAAI,qBAAqB,IAAI,MAAM,GAAG,SAAS,CAE9C;IAED;;;OAGG;IACH,IAAI,iBAAiB,IAAI,SAAS,EAAE,CAEnC;IAED;;OAEG;IACH,IAAI,eAAe,IAAI,SAAS,GAAG,SAAS,CAE3C;IAED,IAAI,OAAO,IAAI,QAAQ,CActB;IAED,IAAI,cAAc,IAAI,QAAQ,CAK7B;IAED,IAAI,aAAa,IAAI,QAAQ,GAAG,SAAS,CAMxC;IAEK,QAAQ,CAAC,OAAO,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC;IAkF/C,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtD;;OAEG;IACH,SAAS,CAAC,qBAAqB,IAAI,IAAI;IAsCjC,KAAK,CAAC,KAAK,EAAE,KAAK;IAMlB,KAAK;CAcZ"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { oConnection, oError, oErrorCodes, } from '@olane/o-core';
|
|
2
|
+
import { oNodeAddress } from '../router/o-node.address.js';
|
|
2
3
|
import { oNodeStreamManager } from './o-node-stream.manager.js';
|
|
3
4
|
export class oNodeConnection extends oConnection {
|
|
4
5
|
constructor(config) {
|
|
@@ -6,10 +7,13 @@ export class oNodeConnection extends oConnection {
|
|
|
6
7
|
this.config = config;
|
|
7
8
|
this.p2pConnection = config.p2pConnection;
|
|
8
9
|
this.reusePolicy = config.reusePolicy ?? 'none';
|
|
10
|
+
this.p2pNode = config.p2pNode;
|
|
9
11
|
// Initialize oNodeStreamManager (stream lifecycle and protocol management)
|
|
10
12
|
this.streamManager = new oNodeStreamManager({
|
|
11
13
|
p2pConnection: this.p2pConnection,
|
|
12
14
|
});
|
|
15
|
+
// Set up persistent identify event listener
|
|
16
|
+
this.setupIdentifyListener();
|
|
13
17
|
}
|
|
14
18
|
get remotePeerId() {
|
|
15
19
|
return this.p2pConnection.remotePeer;
|
|
@@ -31,11 +35,74 @@ export class oNodeConnection extends oConnection {
|
|
|
31
35
|
get streams() {
|
|
32
36
|
return this.streamManager.getAllStreams();
|
|
33
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Get cached identify data for the remote peer.
|
|
40
|
+
* Returns undefined if identify event hasn't been received yet.
|
|
41
|
+
*/
|
|
42
|
+
get cachedIdentifyData() {
|
|
43
|
+
return this.identifyData;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get protocols supported by the remote peer from cached identify data.
|
|
47
|
+
* Returns empty array if identify data not available yet.
|
|
48
|
+
*/
|
|
49
|
+
get remoteProtocols() {
|
|
50
|
+
return this.identifyData?.protocols || [];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get agent version of the remote peer from cached identify data.
|
|
54
|
+
*/
|
|
55
|
+
get remoteAgentVersion() {
|
|
56
|
+
return this.identifyData?.agentVersion;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Get protocol version of the remote peer from cached identify data.
|
|
60
|
+
*/
|
|
61
|
+
get remoteProtocolVersion() {
|
|
62
|
+
return this.identifyData?.protocolVersion;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get listen addresses advertised by the remote peer.
|
|
66
|
+
* Returns empty array if identify data not available yet.
|
|
67
|
+
*/
|
|
68
|
+
get remoteListenAddrs() {
|
|
69
|
+
return this.identifyData?.listenAddrs || [];
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Get our observed address as seen by the remote peer.
|
|
73
|
+
*/
|
|
74
|
+
get observedAddress() {
|
|
75
|
+
return this.identifyData?.observedAddr;
|
|
76
|
+
}
|
|
77
|
+
get address() {
|
|
78
|
+
if (this.identifyData?.protocols &&
|
|
79
|
+
this.identifyData.protocols.length > 0) {
|
|
80
|
+
const filtered = this.identifyData.protocols.filter((p) => p.startsWith('/o/'));
|
|
81
|
+
if (filtered.length > 0) {
|
|
82
|
+
const remoteAddress = oNodeAddress.fromProtocol(filtered[0]);
|
|
83
|
+
return remoteAddress;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return this.config.address;
|
|
87
|
+
}
|
|
88
|
+
get nextHopAddress() {
|
|
89
|
+
if (this.config.nextHopAddress.value === 'o://unknown') {
|
|
90
|
+
return this.address;
|
|
91
|
+
}
|
|
92
|
+
return this.config.nextHopAddress;
|
|
93
|
+
}
|
|
94
|
+
get callerAddress() {
|
|
95
|
+
if (this.p2pConnection.direction === 'inbound') {
|
|
96
|
+
return this.address;
|
|
97
|
+
}
|
|
98
|
+
return this.config.callerAddress;
|
|
99
|
+
}
|
|
34
100
|
async transmit(request) {
|
|
35
101
|
try {
|
|
36
102
|
// Build protocol string
|
|
37
103
|
const protocol = this.nextHopAddress.protocol +
|
|
38
104
|
(this.reusePolicy === 'reuse' ? '/reuse' : '');
|
|
105
|
+
this.logger.debug('Transmitting request on limited connection?', this.config.runOnLimitedConnection);
|
|
39
106
|
const streamConfig = {
|
|
40
107
|
signal: this.abortSignal,
|
|
41
108
|
drainTimeoutMs: this.config.drainTimeoutMs,
|
|
@@ -43,7 +110,7 @@ export class oNodeConnection extends oConnection {
|
|
|
43
110
|
maxOutboundStreams: process.env.MAX_OUTBOUND_STREAMS
|
|
44
111
|
? parseInt(process.env.MAX_OUTBOUND_STREAMS)
|
|
45
112
|
: 1000,
|
|
46
|
-
runOnLimitedConnection: this.config.runOnLimitedConnection ??
|
|
113
|
+
runOnLimitedConnection: this.config.runOnLimitedConnection ?? false,
|
|
47
114
|
};
|
|
48
115
|
// Get stream from StreamManager
|
|
49
116
|
const wrappedStream = await this.streamManager.getOrCreateStream(protocol, this.nextHopAddress, streamConfig);
|
|
@@ -53,9 +120,27 @@ export class oNodeConnection extends oConnection {
|
|
|
53
120
|
// Send the request with backpressure handling
|
|
54
121
|
const data = new TextEncoder().encode(request.toString());
|
|
55
122
|
await this.streamManager.sendLengthPrefixed(stream, data, streamConfig);
|
|
123
|
+
// Determine which stream to wait for response on
|
|
124
|
+
// If _streamId is specified, use that stream (for limited connections with persistent writer stream)
|
|
125
|
+
let responseStream = stream;
|
|
126
|
+
if (request.params._streamId) {
|
|
127
|
+
const specifiedStream = this.streamManager.getStreamById(request.params._streamId);
|
|
128
|
+
if (specifiedStream) {
|
|
129
|
+
responseStream = specifiedStream;
|
|
130
|
+
this.logger.debug('Using specified stream for response', {
|
|
131
|
+
requestStreamId: stream.id,
|
|
132
|
+
responseStreamId: specifiedStream.id,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
this.logger.warn('Specified response stream not found, using request stream', {
|
|
137
|
+
streamId: request.params._streamId,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
56
141
|
// Handle response using StreamManager
|
|
57
142
|
// Pass request ID to enable proper response correlation on shared streams
|
|
58
|
-
const response = await this.streamManager.handleOutgoingStream(
|
|
143
|
+
const response = await this.streamManager.handleOutgoingStream(responseStream, this.emitter, streamConfig, request.id);
|
|
59
144
|
// Handle cleanup of the stream
|
|
60
145
|
await this.postTransmit(wrappedStream);
|
|
61
146
|
return response;
|
|
@@ -71,6 +156,35 @@ export class oNodeConnection extends oConnection {
|
|
|
71
156
|
// Always cleanup streams (no reuse at base layer)
|
|
72
157
|
await this.streamManager.releaseStream(stream.p2pStream.id);
|
|
73
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* Set up persistent listener for identify events from the remote peer
|
|
161
|
+
*/
|
|
162
|
+
setupIdentifyListener() {
|
|
163
|
+
if (!this.p2pNode) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
this.identifyListener = (evt) => {
|
|
167
|
+
const { peerId, protocols, agentVersion, protocolVersion, listenAddrs, observedAddr, } = evt.detail;
|
|
168
|
+
// Only cache if this event is for our remote peer
|
|
169
|
+
if (peerId?.toString() === this.remotePeerId.toString()) {
|
|
170
|
+
this.identifyData = {
|
|
171
|
+
protocols: protocols || [],
|
|
172
|
+
agentVersion,
|
|
173
|
+
protocolVersion,
|
|
174
|
+
listenAddrs: listenAddrs || [],
|
|
175
|
+
observedAddr,
|
|
176
|
+
timestamp: Date.now(),
|
|
177
|
+
};
|
|
178
|
+
this.logger.debug('Cached identify data for peer', {
|
|
179
|
+
peerId: peerId.toString(),
|
|
180
|
+
protocols: this.identifyData.protocols,
|
|
181
|
+
agentVersion: this.identifyData.agentVersion,
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
this.p2pNode.addEventListener('peer:identify', this.identifyListener);
|
|
186
|
+
this.logger.debug('Identify listener set up for connection');
|
|
187
|
+
}
|
|
74
188
|
async abort(error) {
|
|
75
189
|
this.logger.debug('Aborting connection');
|
|
76
190
|
await this.p2pConnection.abort(error);
|
|
@@ -78,6 +192,10 @@ export class oNodeConnection extends oConnection {
|
|
|
78
192
|
}
|
|
79
193
|
async close() {
|
|
80
194
|
this.logger.debug('Closing connection');
|
|
195
|
+
// Remove identify listener
|
|
196
|
+
if (this.p2pNode && this.identifyListener) {
|
|
197
|
+
this.p2pNode.removeEventListener('peer:identify', this.identifyListener);
|
|
198
|
+
}
|
|
81
199
|
// Close stream manager (handles all stream cleanup)
|
|
82
200
|
await this.streamManager.close();
|
|
83
201
|
await this.p2pConnection.close();
|
|
@@ -2,53 +2,34 @@ import { oAddress, oConnectionConfig, oConnectionManager } from '@olane/o-core';
|
|
|
2
2
|
import { Libp2p, Connection } from '@olane/o-config';
|
|
3
3
|
import { oNodeConnectionManagerConfig } from './interfaces/o-node-connection-manager.config.js';
|
|
4
4
|
import { oNodeConnection } from './o-node-connection.js';
|
|
5
|
+
/**
|
|
6
|
+
* Manages oNodeConnection instances, reusing connections when possible.
|
|
7
|
+
*/
|
|
5
8
|
export declare class oNodeConnectionManager extends oConnectionManager {
|
|
6
9
|
readonly config: oNodeConnectionManagerConfig;
|
|
7
10
|
protected p2pNode: Libp2p;
|
|
8
11
|
protected defaultReadTimeoutMs?: number;
|
|
9
12
|
protected defaultDrainTimeoutMs?: number;
|
|
10
13
|
/** Single cache of oNodeConnection instances keyed by address */
|
|
11
|
-
protected cachedConnections: Map<string, oNodeConnection
|
|
14
|
+
protected cachedConnections: Map<string, oNodeConnection>;
|
|
12
15
|
protected pendingDialsByAddress: Map<string, Promise<Connection>>;
|
|
13
16
|
constructor(config: oNodeConnectionManagerConfig);
|
|
14
17
|
/**
|
|
15
18
|
* Set up listeners to maintain connection cache state
|
|
16
19
|
*/
|
|
17
20
|
protected setupConnectionListeners(): void;
|
|
18
|
-
/**
|
|
19
|
-
* Build a stable cache key from an address.
|
|
20
|
-
*
|
|
21
|
-
* We key the cache by address value (e.g., "o://my-tool") to maintain
|
|
22
|
-
* a simple one-to-one mapping between addresses and connections.
|
|
23
|
-
*/
|
|
24
|
-
protected getAddressKey(address: oAddress): string | null;
|
|
25
21
|
/**
|
|
26
22
|
* Extract peer ID string from an address
|
|
27
23
|
* @param address - The address to extract peer ID from
|
|
28
24
|
* @returns The peer ID string or null if not found
|
|
29
25
|
*/
|
|
30
26
|
protected getPeerIdFromAddress(address: oAddress): string | null;
|
|
31
|
-
/**
|
|
32
|
-
* Get the first valid (open) connection for the given address key.
|
|
33
|
-
* Cleans up stale connections from the cache automatically.
|
|
34
|
-
*
|
|
35
|
-
* @param addressKey - The address key to look up
|
|
36
|
-
* @returns A valid oNodeConnection or null if none found
|
|
37
|
-
*/
|
|
38
|
-
protected getValidConnection(addressKey: string): oNodeConnection | null;
|
|
39
27
|
/**
|
|
40
28
|
* Cache an oNodeConnection by its address key.
|
|
41
29
|
* @param conn - The oNodeConnection to cache
|
|
42
30
|
* @param addressKey - The address key to cache under
|
|
43
31
|
*/
|
|
44
|
-
protected cacheConnection(conn: oNodeConnection
|
|
45
|
-
/**
|
|
46
|
-
* Get oNodeConnection by libp2p Connection reference
|
|
47
|
-
* Used to find the correct oNodeConnection for incoming streams
|
|
48
|
-
* @param p2pConnection - The libp2p connection to search for
|
|
49
|
-
* @returns The oNodeConnection or undefined if not found
|
|
50
|
-
*/
|
|
51
|
-
getConnectionByP2pConnection(p2pConnection: Connection): oNodeConnection | undefined;
|
|
32
|
+
protected cacheConnection(conn: oNodeConnection): void;
|
|
52
33
|
/**
|
|
53
34
|
* Get or create a raw p2p connection to the given address.
|
|
54
35
|
* Subclasses can override connect() and use this method to get the underlying p2p connection.
|
|
@@ -59,42 +40,12 @@ export declare class oNodeConnectionManager extends oConnectionManager {
|
|
|
59
40
|
p2pConnection: Connection;
|
|
60
41
|
reuse?: boolean;
|
|
61
42
|
}): Promise<oNodeConnection>;
|
|
43
|
+
getConnectionFromAddress(address: oAddress): oNodeConnection | null;
|
|
62
44
|
/**
|
|
63
45
|
* Connect to a given address, reusing oNodeConnection when possible
|
|
64
46
|
* @param config - Connection configuration
|
|
65
47
|
* @returns The connection object
|
|
66
48
|
*/
|
|
67
49
|
connect(config: oConnectionConfig): Promise<oNodeConnection>;
|
|
68
|
-
/**
|
|
69
|
-
* Check if we have an active connection to the target peer
|
|
70
|
-
* @param address - The address to check
|
|
71
|
-
* @returns true if an active connection exists
|
|
72
|
-
*/
|
|
73
|
-
isCached(address: oAddress): boolean;
|
|
74
|
-
/**
|
|
75
|
-
* Get an existing cached oNodeConnection for the target address
|
|
76
|
-
* @param address - The address to get a connection for
|
|
77
|
-
* @returns The oNodeConnection or null if not found
|
|
78
|
-
*/
|
|
79
|
-
getCachedConnection(address: oAddress): oNodeConnection | null;
|
|
80
|
-
/**
|
|
81
|
-
* Get cache statistics for monitoring and debugging
|
|
82
|
-
* @returns Object containing cache statistics
|
|
83
|
-
*/
|
|
84
|
-
getCacheStats(): {
|
|
85
|
-
cachedAddresses: number;
|
|
86
|
-
totalCachedConnections: number;
|
|
87
|
-
pendingDials: number;
|
|
88
|
-
connectionsByPeer: Array<{
|
|
89
|
-
peerId: string;
|
|
90
|
-
status: string;
|
|
91
|
-
addressKey: string;
|
|
92
|
-
}>;
|
|
93
|
-
};
|
|
94
|
-
/**
|
|
95
|
-
* Clean up all stale (non-open) connections from cache
|
|
96
|
-
* @returns Number of connections removed
|
|
97
|
-
*/
|
|
98
|
-
cleanupStaleConnections(): number;
|
|
99
50
|
}
|
|
100
51
|
//# sourceMappingURL=o-node-connection.manager.d.ts.map
|
|
@@ -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,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,4BAA4B,EAAE,MAAM,kDAAkD,CAAC;AAEhG,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,qBAAa,sBAAuB,SAAQ,kBAAkB;IAQhD,QAAQ,CAAC,MAAM,EAAE,4BAA4B;IAPzD,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACxC,SAAS,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IACzC,iEAAiE;IACjE,SAAS,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,
|
|
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,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,4BAA4B,EAAE,MAAM,kDAAkD,CAAC;AAEhG,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,kBAAkB;IAQhD,QAAQ,CAAC,MAAM,EAAE,4BAA4B;IAPzD,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IACxC,SAAS,CAAC,qBAAqB,CAAC,EAAE,MAAM,CAAC;IACzC,iEAAiE;IACjE,SAAS,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAa;IACtE,SAAS,CAAC,qBAAqB,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAa;gBAEzD,MAAM,EAAE,4BAA4B;IAWzD;;OAEG;IACH,SAAS,CAAC,wBAAwB,IAAI,IAAI;IAY1C;;;;OAIG;IACH,SAAS,CAAC,oBAAoB,CAAC,OAAO,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI;IAahE;;;;OAIG;IACH,SAAS,CAAC,eAAe,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI;IAWtD;;;OAGG;cACa,wBAAwB,CACtC,cAAc,EAAE,QAAQ,EACxB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,UAAU,CAAC;cAoBN,WAAW,CACzB,cAAc,EAAE,QAAQ,EACxB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,UAAU,CAAC;IAqBhB,MAAM,CACV,MAAM,EAAE,iBAAiB,GAAG;QAAE,aAAa,EAAE,UAAU,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GACzE,OAAO,CAAC,eAAe,CAAC;IAgD3B,wBAAwB,CAAC,OAAO,EAAE,QAAQ,GAAG,eAAe,GAAG,IAAI;IAkBnE;;;;OAIG;IACG,OAAO,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,eAAe,CAAC;CAqDnE"}
|