@olane/o-node 0.7.1
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/README.md +1024 -0
- package/dist/src/connection/index.d.ts +5 -0
- package/dist/src/connection/index.d.ts.map +1 -0
- package/dist/src/connection/index.js +4 -0
- package/dist/src/connection/interfaces/o-node-connection-manager.config.d.ts +6 -0
- package/dist/src/connection/interfaces/o-node-connection-manager.config.d.ts.map +1 -0
- package/dist/src/connection/interfaces/o-node-connection-manager.config.js +1 -0
- package/dist/src/connection/interfaces/o-node-connection.config.d.ts +6 -0
- package/dist/src/connection/interfaces/o-node-connection.config.d.ts.map +1 -0
- package/dist/src/connection/interfaces/o-node-connection.config.js +1 -0
- package/dist/src/connection/o-node-connection.d.ts +13 -0
- package/dist/src/connection/o-node-connection.d.ts.map +1 -0
- package/dist/src/connection/o-node-connection.js +51 -0
- package/dist/src/connection/o-node-connection.manager.d.ts +17 -0
- package/dist/src/connection/o-node-connection.manager.d.ts.map +1 -0
- package/dist/src/connection/o-node-connection.manager.js +68 -0
- package/dist/src/index.d.ts +10 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +9 -0
- package/dist/src/interfaces/o-node.config.d.ts +7 -0
- package/dist/src/interfaces/o-node.config.d.ts.map +1 -0
- package/dist/src/interfaces/o-node.config.js +1 -0
- package/dist/src/interfaces/o-node.tool-config.d.ts +4 -0
- package/dist/src/interfaces/o-node.tool-config.d.ts.map +1 -0
- package/dist/src/interfaces/o-node.tool-config.js +1 -0
- package/dist/src/lib/network-activity.lib.d.ts +1 -0
- package/dist/src/lib/network-activity.lib.d.ts.map +1 -0
- package/dist/src/lib/network-activity.lib.js +34 -0
- package/dist/src/nodes/client.node.d.ts +7 -0
- package/dist/src/nodes/client.node.d.ts.map +1 -0
- package/dist/src/nodes/client.node.js +16 -0
- package/dist/src/nodes/index.d.ts +4 -0
- package/dist/src/nodes/index.d.ts.map +1 -0
- package/dist/src/nodes/index.js +3 -0
- package/dist/src/nodes/server.node.d.ts +7 -0
- package/dist/src/nodes/server.node.d.ts.map +1 -0
- package/dist/src/nodes/server.node.js +20 -0
- package/dist/src/nodes/websocket.node.d.ts +7 -0
- package/dist/src/nodes/websocket.node.d.ts.map +1 -0
- package/dist/src/nodes/websocket.node.js +18 -0
- package/dist/src/o-node.d.ts +42 -0
- package/dist/src/o-node.d.ts.map +1 -0
- package/dist/src/o-node.hierarchy-manager.d.ts +15 -0
- package/dist/src/o-node.hierarchy-manager.d.ts.map +1 -0
- package/dist/src/o-node.hierarchy-manager.js +15 -0
- package/dist/src/o-node.js +242 -0
- package/dist/src/o-node.tool.d.ts +16 -0
- package/dist/src/o-node.tool.d.ts.map +1 -0
- package/dist/src/o-node.tool.js +48 -0
- package/dist/src/router/index.d.ts +6 -0
- package/dist/src/router/index.d.ts.map +1 -0
- package/dist/src/router/index.js +5 -0
- package/dist/src/router/interfaces/o-node-router.config.d.ts +3 -0
- package/dist/src/router/interfaces/o-node-router.config.d.ts.map +1 -0
- package/dist/src/router/interfaces/o-node-router.config.js +1 -0
- package/dist/src/router/interfaces/o-node-router.response.d.ts +8 -0
- package/dist/src/router/interfaces/o-node-router.response.d.ts.map +1 -0
- package/dist/src/router/interfaces/o-node-router.response.js +1 -0
- package/dist/src/router/o-node.address.d.ts +18 -0
- package/dist/src/router/o-node.address.d.ts.map +1 -0
- package/dist/src/router/o-node.address.js +29 -0
- package/dist/src/router/o-node.router.d.ts +12 -0
- package/dist/src/router/o-node.router.d.ts.map +1 -0
- package/dist/src/router/o-node.router.js +109 -0
- package/dist/src/router/o-node.transport.d.ts +11 -0
- package/dist/src/router/o-node.transport.d.ts.map +1 -0
- package/dist/src/router/o-node.transport.js +18 -0
- package/dist/src/router/resolvers/index.d.ts +4 -0
- package/dist/src/router/resolvers/index.d.ts.map +1 -0
- package/dist/src/router/resolvers/index.js +3 -0
- package/dist/src/router/resolvers/o-node.child-resolver.d.ts +11 -0
- package/dist/src/router/resolvers/o-node.child-resolver.d.ts.map +1 -0
- package/dist/src/router/resolvers/o-node.child-resolver.js +58 -0
- package/dist/src/router/resolvers/o-node.leader-resolver-fallback.d.ts +8 -0
- package/dist/src/router/resolvers/o-node.leader-resolver-fallback.d.ts.map +1 -0
- package/dist/src/router/resolvers/o-node.leader-resolver-fallback.js +35 -0
- package/dist/src/router/resolvers/o-node.resolver.d.ts +11 -0
- package/dist/src/router/resolvers/o-node.resolver.d.ts.map +1 -0
- package/dist/src/router/resolvers/o-node.resolver.js +41 -0
- package/dist/src/router/resolvers/o-node.search-resolver.d.ts +8 -0
- package/dist/src/router/resolvers/o-node.search-resolver.d.ts.map +1 -0
- package/dist/src/router/resolvers/o-node.search-resolver.js +60 -0
- package/dist/src/router/route.request.d.ts +14 -0
- package/dist/src/router/route.request.d.ts.map +1 -0
- package/dist/src/router/route.request.js +1 -0
- package/dist/src/utils/network.utils.d.ts +20 -0
- package/dist/src/utils/network.utils.d.ts.map +1 -0
- package/dist/src/utils/network.utils.js +74 -0
- package/dist/test/o-node.spec.d.ts +2 -0
- package/dist/test/o-node.spec.d.ts.map +1 -0
- package/dist/test/o-node.spec.js +20 -0
- package/package.json +68 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { bootstrap, createNode, defaultLibp2pConfig, } from '@olane/o-config';
|
|
2
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
3
|
+
import { oNodeRouter } from './router/o-node.router.js';
|
|
4
|
+
import { oNodeHierarchyManager } from './o-node.hierarchy-manager.js';
|
|
5
|
+
import { oNodeTransport } from './router/o-node.transport.js';
|
|
6
|
+
import { CoreUtils, NodeState, NodeType, oAddress, RestrictedAddresses, } from '@olane/o-core';
|
|
7
|
+
import { oNodeAddress } from './router/o-node.address.js';
|
|
8
|
+
import { oNodeConnectionManager } from './connection/o-node-connection.manager.js';
|
|
9
|
+
import { oNodeResolver } from './router/resolvers/o-node.resolver.js';
|
|
10
|
+
import { NetworkUtils } from './utils/network.utils.js';
|
|
11
|
+
import { oMethodResolver, oToolBase } from '@olane/o-tool';
|
|
12
|
+
import { oLeaderResolverFallback } from './router/index.js';
|
|
13
|
+
export class oNode extends oToolBase {
|
|
14
|
+
constructor(config) {
|
|
15
|
+
super(config);
|
|
16
|
+
this.didRegister = false;
|
|
17
|
+
this.config = config;
|
|
18
|
+
}
|
|
19
|
+
get leader() {
|
|
20
|
+
return this.isLeader ? this.address : this.config?.leader || null;
|
|
21
|
+
}
|
|
22
|
+
get networkConfig() {
|
|
23
|
+
return this.config.network || defaultLibp2pConfig;
|
|
24
|
+
}
|
|
25
|
+
get parentPeerId() {
|
|
26
|
+
if (!this.parent || this.parent?.transports?.length === 0) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
const transport = this.parent?.transports[0];
|
|
30
|
+
const peerId = transport.toPeerId();
|
|
31
|
+
return peerId;
|
|
32
|
+
}
|
|
33
|
+
configureTransports() {
|
|
34
|
+
return [...(defaultLibp2pConfig.transports || [])];
|
|
35
|
+
}
|
|
36
|
+
async initializeRouter() {
|
|
37
|
+
this.hierarchyManager = new oNodeHierarchyManager({
|
|
38
|
+
leaders: this.config.leader ? [this.config.leader] : [],
|
|
39
|
+
parents: this.config.parent ? [this.config.parent] : [],
|
|
40
|
+
children: [],
|
|
41
|
+
});
|
|
42
|
+
this.router = new oNodeRouter();
|
|
43
|
+
}
|
|
44
|
+
get staticAddress() {
|
|
45
|
+
return this.config.address;
|
|
46
|
+
}
|
|
47
|
+
get parentTransports() {
|
|
48
|
+
return this.config.parent?.transports || [];
|
|
49
|
+
}
|
|
50
|
+
get transports() {
|
|
51
|
+
return this.p2pNode
|
|
52
|
+
.getMultiaddrs()
|
|
53
|
+
.map((multiaddr) => new oNodeTransport(multiaddr.toString()));
|
|
54
|
+
}
|
|
55
|
+
async unregister() {
|
|
56
|
+
if (this.type === NodeType.LEADER) {
|
|
57
|
+
this.logger.debug('Skipping unregistration, node is leader');
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (!this.config.leader) {
|
|
61
|
+
this.logger.debug('No leader found, skipping unregistration');
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const address = new oNodeAddress(RestrictedAddresses.REGISTRY);
|
|
65
|
+
// attempt to unregister from the network
|
|
66
|
+
const params = {
|
|
67
|
+
method: 'remove',
|
|
68
|
+
params: {
|
|
69
|
+
peerId: this.peerId.toString(),
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
await this.use(address, params);
|
|
73
|
+
}
|
|
74
|
+
async register() {
|
|
75
|
+
if (this.type === NodeType.LEADER) {
|
|
76
|
+
this.logger.debug('Skipping registration, node is leader');
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (this.didRegister) {
|
|
80
|
+
this.logger.debug('Node already registered, skipping registration');
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
this.didRegister = true;
|
|
84
|
+
this.logger.debug('Registering node...');
|
|
85
|
+
// register with the leader global registry
|
|
86
|
+
if (!this.config.leader) {
|
|
87
|
+
this.logger.warn('No leaders found, skipping registration');
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
this.logger.debug('Registering node with leader...');
|
|
92
|
+
}
|
|
93
|
+
const address = oAddress.registry();
|
|
94
|
+
const params = {
|
|
95
|
+
method: 'commit',
|
|
96
|
+
params: {
|
|
97
|
+
peerId: this.peerId.toString(),
|
|
98
|
+
address: this.address.toString(),
|
|
99
|
+
protocols: this.p2pNode.getProtocols(),
|
|
100
|
+
transports: this.transports,
|
|
101
|
+
staticAddress: this.staticAddress.toString(),
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
await this.use(address, params);
|
|
105
|
+
this.logger.debug('Registration successful');
|
|
106
|
+
}
|
|
107
|
+
extractMethod(address) {
|
|
108
|
+
return address.protocol.split('/').pop() || '';
|
|
109
|
+
}
|
|
110
|
+
async start() {
|
|
111
|
+
await super.start();
|
|
112
|
+
await NetworkUtils.advertiseToNetwork(this.address, this.staticAddress, this.p2pNode);
|
|
113
|
+
}
|
|
114
|
+
async validateJoinRequest(request) {
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Configure the libp2p node
|
|
119
|
+
* @returns The libp2p config
|
|
120
|
+
*/
|
|
121
|
+
async configure() {
|
|
122
|
+
const params = {
|
|
123
|
+
...this.networkConfig,
|
|
124
|
+
transports: this.configureTransports(),
|
|
125
|
+
connectionManager: {
|
|
126
|
+
...(this.networkConfig.connectionManager || {}),
|
|
127
|
+
},
|
|
128
|
+
listeners: (this.config.network?.listeners ||
|
|
129
|
+
defaultLibp2pConfig.listeners ||
|
|
130
|
+
[]).concat(`/memory/${uuidv4()}`), // ensure we allow for local in-memory communication
|
|
131
|
+
};
|
|
132
|
+
// if the seed is provided, use it to generate the private key
|
|
133
|
+
if (this.config.seed) {
|
|
134
|
+
this.logger.debug('Seed provided, generating private key...');
|
|
135
|
+
const privateKey = await CoreUtils.generatePrivateKey(this.config.seed);
|
|
136
|
+
params.privateKey = privateKey;
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
this.logger.debug('No seed provided, generating private key...');
|
|
140
|
+
this.logger.debug('Without providing a seed, this node peer id will be destroyed after the node shuts down.');
|
|
141
|
+
// TODO: add a link to documentation about how to setup a seed
|
|
142
|
+
}
|
|
143
|
+
// this is a child node of the network, so communication is heavily restricted
|
|
144
|
+
if (this.parentTransports.length > 0) {
|
|
145
|
+
// peer discovery is only allowed through the parent transports
|
|
146
|
+
const transports = this.parentTransports.map((t) => t.toMultiaddr().toString()) || [];
|
|
147
|
+
this.logger.debug('Parent transports: ', transports);
|
|
148
|
+
params.peerDiscovery = [
|
|
149
|
+
bootstrap({
|
|
150
|
+
list: transports.concat(this.leader?.libp2pTransports.map((t) => t.toString()) || []),
|
|
151
|
+
}),
|
|
152
|
+
...(defaultLibp2pConfig.peerDiscovery || []),
|
|
153
|
+
];
|
|
154
|
+
// // let's make sure we only allow communication through the parent transports
|
|
155
|
+
params.connectionGater = {
|
|
156
|
+
// who can call us?
|
|
157
|
+
denyInboundEncryptedConnection: (peerId, maConn) => {
|
|
158
|
+
// deny all inbound connections unless they are from a parent transport
|
|
159
|
+
if (this.parentPeerId === peerId.toString()) {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
if (this.hierarchyManager.children.some((c) => c.libp2pTransports.some((t) => t.toPeerId() === peerId.toString()))) {
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
// allow leader inbounds
|
|
166
|
+
if (this.config.type === NodeType.LEADER) {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
// deny everything else
|
|
170
|
+
return true;
|
|
171
|
+
},
|
|
172
|
+
// allow the user to override the default connection gater
|
|
173
|
+
...(this.config.network?.connectionGater || {}),
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
// handle the address encapsulation
|
|
177
|
+
if (this.config.leader &&
|
|
178
|
+
!this.address.protocol.includes(this.config.leader.protocol)) {
|
|
179
|
+
const parentAddress = this.config.parent || this.config.leader;
|
|
180
|
+
this.logger.debug('Encapsulating address: ' + this.address.toString(), parentAddress.toString());
|
|
181
|
+
this.address = CoreUtils.childAddress(parentAddress, this.address);
|
|
182
|
+
this.logger.debug('Encapsulated address: ' + this.address.toString());
|
|
183
|
+
}
|
|
184
|
+
return params;
|
|
185
|
+
}
|
|
186
|
+
async connect(nextHopAddress, targetAddress) {
|
|
187
|
+
if (!this.connectionManager) {
|
|
188
|
+
this.logger.error('Connection manager not initialized');
|
|
189
|
+
throw new Error('Node is not ready to connect to other nodes');
|
|
190
|
+
}
|
|
191
|
+
const connection = await this.connectionManager
|
|
192
|
+
.connect({
|
|
193
|
+
address: targetAddress,
|
|
194
|
+
nextHopAddress,
|
|
195
|
+
callerAddress: this.address,
|
|
196
|
+
})
|
|
197
|
+
.catch((error) => {
|
|
198
|
+
// TODO: we need to handle this better and document
|
|
199
|
+
if (error.message === 'Can not dial self') {
|
|
200
|
+
this.logger.error('Make sure you are entering the network not directly through the leader node.');
|
|
201
|
+
}
|
|
202
|
+
throw error;
|
|
203
|
+
});
|
|
204
|
+
if (!connection) {
|
|
205
|
+
throw new Error('Connection failed');
|
|
206
|
+
}
|
|
207
|
+
return connection;
|
|
208
|
+
}
|
|
209
|
+
async initialize() {
|
|
210
|
+
this.logger.debug('Initializing node...');
|
|
211
|
+
if (this.p2pNode && this.state !== NodeState.STOPPED) {
|
|
212
|
+
throw new Error('Node is not in a valid state to be initialized');
|
|
213
|
+
}
|
|
214
|
+
if (!this.address.validate()) {
|
|
215
|
+
throw new Error('Invalid address');
|
|
216
|
+
}
|
|
217
|
+
const params = await this.configure();
|
|
218
|
+
this.p2pNode = await createNode(params);
|
|
219
|
+
await this.initializeRouter();
|
|
220
|
+
this.logger.debug('Node initialized!', this.transports.map((t) => t.toString()));
|
|
221
|
+
this.address.setTransports(this.transports);
|
|
222
|
+
this.peerId = this.p2pNode.peerId;
|
|
223
|
+
// initialize connection manager
|
|
224
|
+
this.connectionManager = new oNodeConnectionManager({
|
|
225
|
+
p2pNode: this.p2pNode,
|
|
226
|
+
});
|
|
227
|
+
// initialize address resolution
|
|
228
|
+
this.router.addResolver(new oMethodResolver(this.address));
|
|
229
|
+
this.router.addResolver(new oNodeResolver(this.address));
|
|
230
|
+
// setup a fallback resolver for non-leader nodes
|
|
231
|
+
if (this.isLeader === false) {
|
|
232
|
+
this.logger.debug('Adding leader resolver fallback...');
|
|
233
|
+
this.router.addResolver(new oLeaderResolverFallback(this.address));
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
async teardown() {
|
|
237
|
+
await super.teardown();
|
|
238
|
+
if (this.p2pNode) {
|
|
239
|
+
await this.p2pNode.stop();
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { oAddress } from '@olane/o-core';
|
|
2
|
+
import { IncomingStreamData } from '@olane/o-config';
|
|
3
|
+
import { oServerNode } from './nodes/server.node.js';
|
|
4
|
+
declare const oNodeTool_base: typeof oServerNode;
|
|
5
|
+
/**
|
|
6
|
+
* oTool is a mixin that extends the base class and implements the oTool interface
|
|
7
|
+
* @param Base - The base class to extend
|
|
8
|
+
* @returns A new class that extends the base class and implements the oTool interface
|
|
9
|
+
*/
|
|
10
|
+
export declare class oNodeTool extends oNodeTool_base {
|
|
11
|
+
handleProtocol(address: oAddress): Promise<void>;
|
|
12
|
+
initialize(): Promise<void>;
|
|
13
|
+
handleStream(streamData: IncomingStreamData): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=o-node.tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"o-node.tool.d.ts","sourceRoot":"","sources":["../../src/o-node.tool.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,QAAQ,EAKT,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;;AAErD;;;;GAIG;AACH,qBAAa,SAAU,SAAQ,cAAkB;IACzC,cAAc,CAAC,OAAO,EAAE,QAAQ;IAKhC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAW3B,YAAY,CAAC,UAAU,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;CAgClE"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { CoreUtils, oError, oErrorCodes, oRequest, } from '@olane/o-core';
|
|
2
|
+
import { oTool } from '@olane/o-tool';
|
|
3
|
+
import { oServerNode } from './nodes/server.node.js';
|
|
4
|
+
/**
|
|
5
|
+
* oTool is a mixin that extends the base class and implements the oTool interface
|
|
6
|
+
* @param Base - The base class to extend
|
|
7
|
+
* @returns A new class that extends the base class and implements the oTool interface
|
|
8
|
+
*/
|
|
9
|
+
export class oNodeTool extends oTool(oServerNode) {
|
|
10
|
+
async handleProtocol(address) {
|
|
11
|
+
this.logger.debug('Handling protocol: ' + address.protocol);
|
|
12
|
+
await this.p2pNode.handle(address.protocol, this.handleStream.bind(this));
|
|
13
|
+
}
|
|
14
|
+
async initialize() {
|
|
15
|
+
await super.initialize();
|
|
16
|
+
await this.handleProtocol(this.address);
|
|
17
|
+
if (this.staticAddress &&
|
|
18
|
+
this.staticAddress?.toString() !== this.address.toString()) {
|
|
19
|
+
await this.handleProtocol(this.staticAddress);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async handleStream(streamData) {
|
|
23
|
+
const { stream } = streamData;
|
|
24
|
+
const requestConfig = await CoreUtils.processStream(stream);
|
|
25
|
+
const request = new oRequest(requestConfig);
|
|
26
|
+
let success = true;
|
|
27
|
+
const result = await this.execute(request, stream).catch((error) => {
|
|
28
|
+
this.logger.error('Error executing tool: ', error, typeof error);
|
|
29
|
+
success = false;
|
|
30
|
+
const responseError = error instanceof oError
|
|
31
|
+
? error
|
|
32
|
+
: new oError(oErrorCodes.UNKNOWN, error.message);
|
|
33
|
+
return {
|
|
34
|
+
error: responseError.toJSON(),
|
|
35
|
+
};
|
|
36
|
+
});
|
|
37
|
+
if (success) {
|
|
38
|
+
this.metrics.successCount++;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
this.metrics.errorCount++;
|
|
42
|
+
}
|
|
43
|
+
// compose the response & add the expected connection + request fields
|
|
44
|
+
const response = CoreUtils.buildResponse(request, result, result?.error);
|
|
45
|
+
// add the request method to the response
|
|
46
|
+
return CoreUtils.sendResponse(response, stream);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/router/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"o-node-router.config.d.ts","sourceRoot":"","sources":["../../../../src/router/interfaces/o-node-router.config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;CAAG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { oNodeAddress } from '../o-node.address';
|
|
2
|
+
import { oRouterRequest, RouteResponse } from '@olane/o-core';
|
|
3
|
+
export interface oNodeRouterResponse extends RouteResponse {
|
|
4
|
+
nextHopAddress: oNodeAddress;
|
|
5
|
+
targetAddress: oNodeAddress;
|
|
6
|
+
requestOverride?: oRouterRequest;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=o-node-router.response.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"o-node-router.response.d.ts","sourceRoot":"","sources":["../../../../src/router/interfaces/o-node-router.response.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE9D,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD,cAAc,EAAE,YAAY,CAAC;IAC7B,aAAa,EAAE,YAAY,CAAC;IAC5B,eAAe,CAAC,EAAE,cAAc,CAAC;CAClC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Multiaddr } from '@olane/o-config';
|
|
2
|
+
import { oNodeTransport } from './o-node.transport.js';
|
|
3
|
+
import { oAddress } from '@olane/o-core';
|
|
4
|
+
export declare class oNodeAddress extends oAddress {
|
|
5
|
+
readonly value: string;
|
|
6
|
+
transports: oNodeTransport[];
|
|
7
|
+
constructor(value: string, transports?: oNodeTransport[]);
|
|
8
|
+
static fromJSON(json: {
|
|
9
|
+
value: string;
|
|
10
|
+
transports: string[] | Multiaddr[];
|
|
11
|
+
}): oNodeAddress;
|
|
12
|
+
get libp2pTransports(): oNodeTransport[];
|
|
13
|
+
get customTransports(): oNodeTransport[];
|
|
14
|
+
toString(): string;
|
|
15
|
+
toMultiaddr(): Multiaddr;
|
|
16
|
+
static fromMultiaddr(ma: Multiaddr): oAddress;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=o-node.address.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"o-node.address.d.ts","sourceRoot":"","sources":["../../../src/router/o-node.address.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAa,MAAM,iBAAiB,CAAC;AAEvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAqB,QAAQ,EAAiB,MAAM,eAAe,CAAC;AAE3E,qBAAa,YAAa,SAAQ,QAAQ;aAItB,KAAK,EAAE,MAAM;IAHxB,UAAU,EAAE,cAAc,EAAE,CAAM;gBAGvB,KAAK,EAAE,MAAM,EAC7B,UAAU,GAAE,cAAc,EAAO;IAMnC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE;QACpB,KAAK,EAAE,MAAM,CAAC;QACd,UAAU,EAAE,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC;KACpC,GAAG,YAAY;IAShB,IAAI,gBAAgB,IAAI,cAAc,EAAE,CAEvC;IAED,IAAI,gBAAgB,IAAI,cAAc,EAAE,CAEvC;IAED,QAAQ,IAAI,MAAM;IAIlB,WAAW,IAAI,SAAS;IAIxB,MAAM,CAAC,aAAa,CAAC,EAAE,EAAE,SAAS,GAAG,QAAQ;CAG9C"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { multiaddr } from '@olane/o-config';
|
|
2
|
+
import { oNodeTransport } from './o-node.transport.js';
|
|
3
|
+
import { oAddress, TransportType } from '@olane/o-core';
|
|
4
|
+
export class oNodeAddress extends oAddress {
|
|
5
|
+
constructor(value, transports = []) {
|
|
6
|
+
super(value);
|
|
7
|
+
this.value = value;
|
|
8
|
+
this.transports = [];
|
|
9
|
+
this.transports = transports;
|
|
10
|
+
}
|
|
11
|
+
static fromJSON(json) {
|
|
12
|
+
return new oNodeAddress(json.value, json.transports.map((t) => new oNodeTransport(t)));
|
|
13
|
+
}
|
|
14
|
+
get libp2pTransports() {
|
|
15
|
+
return this.transports.filter((t) => t.type === TransportType.LIBP2P) || [];
|
|
16
|
+
}
|
|
17
|
+
get customTransports() {
|
|
18
|
+
return this.transports.filter((t) => t.type === TransportType.CUSTOM) || [];
|
|
19
|
+
}
|
|
20
|
+
toString() {
|
|
21
|
+
return this.value;
|
|
22
|
+
}
|
|
23
|
+
toMultiaddr() {
|
|
24
|
+
return multiaddr(this.protocol);
|
|
25
|
+
}
|
|
26
|
+
static fromMultiaddr(ma) {
|
|
27
|
+
return new oAddress(ma.toString().replace('/o/', 'o://'));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { oNodeAddress } from './o-node.address.js';
|
|
2
|
+
import { oRouterRequest, RouteResponse } from '@olane/o-core';
|
|
3
|
+
import type { oNode } from '../o-node.js';
|
|
4
|
+
import { oToolRouter } from '@olane/o-tool';
|
|
5
|
+
export declare class oNodeRouter extends oToolRouter {
|
|
6
|
+
constructor();
|
|
7
|
+
protected forward(address: oNodeAddress, request: oRouterRequest, node: oNode): Promise<any>;
|
|
8
|
+
private handleExternalAddress;
|
|
9
|
+
translate(address: oNodeAddress, node: oNode): Promise<RouteResponse>;
|
|
10
|
+
isInternal(addressWithTransports: oNodeAddress, node: oNode): boolean;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=o-node.router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"o-node.router.d.ts","sourceRoot":"","sources":["../../../src/router/o-node.router.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAOL,cAAc,EACd,aAAa,EACd,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAI5C,qBAAa,WAAY,SAAQ,WAAW;;cAK1B,OAAO,CACrB,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,cAAc,EACvB,IAAI,EAAE,KAAK,GACV,OAAO,CAAC,GAAG,CAAC;IAgFf,OAAO,CAAC,qBAAqB;IAsBvB,SAAS,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,GAAG,OAAO,CAAC,aAAa,CAAC;IAoB3E,UAAU,CAAC,qBAAqB,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,GAAG,OAAO;CAetE"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { oNodeAddress } from './o-node.address.js';
|
|
2
|
+
import { CoreUtils, oAddress, oError, oErrorCodes, oRequest, } from '@olane/o-core';
|
|
3
|
+
import { oToolRouter } from '@olane/o-tool';
|
|
4
|
+
import { pipe, pushable } from '@olane/o-config';
|
|
5
|
+
export class oNodeRouter extends oToolRouter {
|
|
6
|
+
constructor() {
|
|
7
|
+
super();
|
|
8
|
+
}
|
|
9
|
+
async forward(address, request, node) {
|
|
10
|
+
if (!request.stream) {
|
|
11
|
+
throw new oError(oErrorCodes.INVALID_REQUEST, 'Stream is required');
|
|
12
|
+
}
|
|
13
|
+
const stream = request.stream;
|
|
14
|
+
let nextHopRequest = new oRequest({
|
|
15
|
+
method: request.method,
|
|
16
|
+
params: request.params,
|
|
17
|
+
id: request.id,
|
|
18
|
+
});
|
|
19
|
+
// are we dialing self?
|
|
20
|
+
if (node.address.toString() === address.toString()) {
|
|
21
|
+
const { payload } = request.params;
|
|
22
|
+
const params = payload.params;
|
|
23
|
+
nextHopRequest = new oRequest({
|
|
24
|
+
method: payload.method,
|
|
25
|
+
params: {
|
|
26
|
+
...params,
|
|
27
|
+
},
|
|
28
|
+
id: request.id,
|
|
29
|
+
});
|
|
30
|
+
const result = await node.execute(nextHopRequest);
|
|
31
|
+
const response = CoreUtils.buildResponse(nextHopRequest, result, result?.error);
|
|
32
|
+
// add the request method to the response
|
|
33
|
+
return CoreUtils.sendResponse(response, stream);
|
|
34
|
+
}
|
|
35
|
+
// next hop is the destination address
|
|
36
|
+
if (address
|
|
37
|
+
?.toStaticAddress()
|
|
38
|
+
.equals(new oAddress(request?.params?.address).toStaticAddress())) {
|
|
39
|
+
// reached destination, so change from route to actual request
|
|
40
|
+
const { payload } = request.params;
|
|
41
|
+
const params = payload.params;
|
|
42
|
+
nextHopRequest = new oRequest({
|
|
43
|
+
method: payload.method,
|
|
44
|
+
params: {
|
|
45
|
+
...params,
|
|
46
|
+
},
|
|
47
|
+
id: request.id,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
// dial the target
|
|
51
|
+
try {
|
|
52
|
+
const targetStream = await node?.p2pNode.dialProtocol(address.libp2pTransports.map((t) => t.toMultiaddr()), address.protocol);
|
|
53
|
+
if (!targetStream) {
|
|
54
|
+
throw new oError(oErrorCodes.FAILED_TO_DIAL_TARGET, 'Failed to dial target');
|
|
55
|
+
}
|
|
56
|
+
const pushableStream = pushable();
|
|
57
|
+
pushableStream.push(new TextEncoder().encode(nextHopRequest.toString()));
|
|
58
|
+
pushableStream.end();
|
|
59
|
+
await targetStream.sink(pushableStream);
|
|
60
|
+
await pipe(targetStream.source, stream?.sink);
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
if (error?.name === 'UnsupportedProtocolError') {
|
|
64
|
+
throw new oError(oErrorCodes.NOT_FOUND, 'Address not found');
|
|
65
|
+
}
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
handleExternalAddress(address, node) {
|
|
70
|
+
// determine if this is external
|
|
71
|
+
const isInternal = this.isInternal(address, node);
|
|
72
|
+
if (!isInternal) {
|
|
73
|
+
// external address, so we need to route
|
|
74
|
+
this.logger.debug('Address is external, routing...', address);
|
|
75
|
+
// route to leader of external OS
|
|
76
|
+
return {
|
|
77
|
+
nextHopAddress: new oNodeAddress(oAddress.leader().toString(), address.libp2pTransports),
|
|
78
|
+
targetAddress: address,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
async translate(address, node) {
|
|
84
|
+
const externalRoute = this.handleExternalAddress(address, node);
|
|
85
|
+
if (externalRoute) {
|
|
86
|
+
return externalRoute;
|
|
87
|
+
}
|
|
88
|
+
const { nextHopAddress, targetAddress, requestOverride } = await this.addressResolution.resolve({
|
|
89
|
+
address,
|
|
90
|
+
node,
|
|
91
|
+
targetAddress: address,
|
|
92
|
+
});
|
|
93
|
+
return {
|
|
94
|
+
nextHopAddress,
|
|
95
|
+
targetAddress: targetAddress,
|
|
96
|
+
requestOverride,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
isInternal(addressWithTransports, node) {
|
|
100
|
+
if (addressWithTransports.paths.indexOf(oAddress.leader().paths) !== -1 && // if the address has a leader
|
|
101
|
+
addressWithTransports.libp2pTransports?.length > 0) {
|
|
102
|
+
// transports are provided, let's see if they match our known leaders
|
|
103
|
+
const isLeaderRef = addressWithTransports.toString() === oAddress.leader().toString();
|
|
104
|
+
const isOurLeaderRef = node.hierarchyManager.leaders.some((l) => l.equals(addressWithTransports));
|
|
105
|
+
return isLeaderRef || isOurLeaderRef;
|
|
106
|
+
}
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Multiaddr } from '@olane/o-config';
|
|
2
|
+
import { oTransport, TransportType } from '@olane/o-core';
|
|
3
|
+
export declare class oNodeTransport extends oTransport {
|
|
4
|
+
readonly type: TransportType;
|
|
5
|
+
value: Multiaddr | string;
|
|
6
|
+
constructor(value: Multiaddr | string);
|
|
7
|
+
toMultiaddr(): Multiaddr;
|
|
8
|
+
toString(): string;
|
|
9
|
+
toPeerId(): string;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=o-node.transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"o-node.transport.d.ts","sourceRoot":"","sources":["../../../src/router/o-node.transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE1D,qBAAa,cAAe,SAAQ,UAAU;IAC5C,SAAgB,IAAI,EAAE,aAAa,CAAwB;IACpD,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC;gBAErB,KAAK,EAAE,SAAS,GAAG,MAAM;IAKrC,WAAW,IAAI,SAAS;IAIxB,QAAQ,IAAI,MAAM;IAIlB,QAAQ,IAAI,MAAM;CAGnB"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { multiaddr } from '@olane/o-config';
|
|
2
|
+
import { oTransport, TransportType } from '@olane/o-core';
|
|
3
|
+
export class oNodeTransport extends oTransport {
|
|
4
|
+
constructor(value) {
|
|
5
|
+
super(value);
|
|
6
|
+
this.type = TransportType.LIBP2P;
|
|
7
|
+
this.value = value;
|
|
8
|
+
}
|
|
9
|
+
toMultiaddr() {
|
|
10
|
+
return multiaddr(this.toString());
|
|
11
|
+
}
|
|
12
|
+
toString() {
|
|
13
|
+
return this.value.toString();
|
|
14
|
+
}
|
|
15
|
+
toPeerId() {
|
|
16
|
+
return this.value.toString().split('/p2p/')[1];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/router/resolvers/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,sCAAsC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { oAddressResolver, TransportType } from '@olane/o-core';
|
|
2
|
+
import { oNodeAddress } from '../o-node.address.js';
|
|
3
|
+
import { oNodeRouterResponse } from '../interfaces/o-node-router.response.js';
|
|
4
|
+
import { ResolveRequest } from '@olane/o-core';
|
|
5
|
+
export declare class oNodeChildResolver extends oAddressResolver {
|
|
6
|
+
protected readonly address: oNodeAddress;
|
|
7
|
+
constructor(address: oNodeAddress);
|
|
8
|
+
get supportedTransports(): TransportType[];
|
|
9
|
+
resolve(routeRequest: ResolveRequest): Promise<oNodeRouterResponse>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=o-node.child-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"o-node.child-resolver.d.ts","sourceRoot":"","sources":["../../../../src/router/resolvers/o-node.child-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAEhB,aAAa,EAEd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,qBAAa,kBAAmB,SAAQ,gBAAgB;IAC1C,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,YAAY;gBAArB,OAAO,EAAE,YAAY;IAIpD,IAAI,mBAAmB,IAAI,aAAa,EAAE,CAEzC;IAEK,OAAO,CAAC,YAAY,EAAE,cAAc,GAAG,OAAO,CAAC,mBAAmB,CAAC;CA4D1E"}
|