mirror of
https://github.com/fluencelabs/fluence-js.git
synced 2025-06-21 20:01:33 +00:00
21
packages/fluence-connection/.gitignore
vendored
Normal file
21
packages/fluence-connection/.gitignore
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
bundle/
|
||||
|
||||
dist
|
||||
esm
|
||||
types
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
.idea
|
12
packages/fluence-connection/.npmignore
Normal file
12
packages/fluence-connection/.npmignore
Normal file
@ -0,0 +1,12 @@
|
||||
.idea
|
||||
.gitignore
|
||||
node_modules
|
||||
types
|
||||
|
||||
src/
|
||||
|
||||
tsconfig.json
|
||||
webpack.config.js
|
||||
|
||||
bundle
|
||||
pkg
|
8
packages/fluence-connection/.prettierrc.js
Normal file
8
packages/fluence-connection/.prettierrc.js
Normal file
@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
semi: true,
|
||||
trailingComma: "all",
|
||||
singleQuote: true,
|
||||
printWidth: 120,
|
||||
tabWidth: 4,
|
||||
useTabs: false
|
||||
};
|
13
packages/fluence-connection/CONTRIBUTING.md
Normal file
13
packages/fluence-connection/CONTRIBUTING.md
Normal file
@ -0,0 +1,13 @@
|
||||
## Contribute Code
|
||||
|
||||
You are welcome to contribute to Fluence.
|
||||
|
||||
Things you need to know:
|
||||
|
||||
1. You need to **agree to the Contributors License Agreement**. This is a common practice in all major Open Source projects. At the current moment we are unable to accept contributions made on behalf of a company. Only individual contributions will be accepted.
|
||||
2. **Not all proposed contributions can be accepted**. Some features may e.g. just fit a third-party add-on better. The contribution must fit the overall direction of Fluence and really improve it. The more effort you invest, the better you should clarify in advance whether the contribution fits: the best way would be to just open an issue to discuss the contribution you plan to make.
|
||||
|
||||
### Contributor License Agreement
|
||||
|
||||
When you contribute, you have to be aware that your contribution is covered by **Apache License 2.0**, but might relicensed under few other software licenses mentioned in the **Contributor License Agreement**.
|
||||
In particular you need to agree to the [Contributor License Agreement](https://gist.github.com/fluencelabs-org/3f4cbb3cc14c1c0fb9ad99d8f7316ed7). If you agree to its content, you simply have to click on the link posted by the CLA assistant as a comment to the pull request. Click it to check the CLA, then accept it on the following screen if you agree to it. CLA assistant will save this decision for upcoming contributions and will notify you if there is any change to the CLA in the meantime.
|
11
packages/fluence-connection/README.md
Normal file
11
packages/fluence-connection/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# FluenceJS connection
|
||||
|
||||
This package is a part of FluenceJS, the official implementation of the Fluence Peer in typescript. See the [FluenceJS repo](https://github.com/fluencelabs/fluence-js) for more info
|
||||
|
||||
## Contributing
|
||||
|
||||
While the project is still in the early stages of development, you are welcome to track progress and contribute. As the project is undergoing rapid changes, interested contributors should contact the team before embarking on larger pieces of work. All contributors should consult with and agree to our [basic contributing rules](CONTRIBUTING.md).
|
||||
|
||||
## License
|
||||
|
||||
[Apache 2.0](LICENSE)
|
33
packages/fluence-connection/package.json
Normal file
33
packages/fluence-connection/package.json
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "@fluencelabs/connection",
|
||||
"version": "0.1.0",
|
||||
"description": "Fluence connection",
|
||||
"main": "./dist/index.js",
|
||||
"typings": "./dist/index.d.ts",
|
||||
"engines": {
|
||||
"node": ">=10",
|
||||
"pnpm": ">=3"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc"
|
||||
},
|
||||
"repository": "https://github.com/fluencelabs/fluence-js",
|
||||
"author": "Fluence Labs",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@fluencelabs/interfaces": "workspace:0.1.0",
|
||||
"peer-id": "0.16.0",
|
||||
"it-length-prefixed": "5.0.3",
|
||||
"it-pipe": "1.1.0",
|
||||
"@chainsafe/libp2p-noise": "^4.1.1",
|
||||
"libp2p": "0.36.2",
|
||||
"libp2p-interfaces": "^4.0.6",
|
||||
"libp2p-mplex": "0.10.7",
|
||||
"libp2p-websockets": "0.16.2",
|
||||
"loglevel": "1.8.0",
|
||||
"multiaddr": "10.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^4.6.4"
|
||||
}
|
||||
}
|
177
packages/fluence-connection/src/index.ts
Normal file
177
packages/fluence-connection/src/index.ts
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright 2020 Fluence Labs Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { FluenceConnection, ParticleHandler, PeerIdB58 } from '@fluencelabs/interfaces';
|
||||
// @ts-ignore
|
||||
import Websockets from 'libp2p-websockets';
|
||||
// @ts-ignore
|
||||
import Mplex from 'libp2p-mplex';
|
||||
import Lib2p2Peer from 'libp2p';
|
||||
import { decode, encode } from 'it-length-prefixed';
|
||||
import { pipe } from 'it-pipe';
|
||||
import * as log from 'loglevel';
|
||||
import { Noise } from '@chainsafe/libp2p-noise';
|
||||
import PeerId from 'peer-id';
|
||||
import type { MultiaddrInput } from 'multiaddr';
|
||||
import { Multiaddr } from 'multiaddr';
|
||||
// @ts-ignore
|
||||
import { all as allow_all } from 'libp2p-websockets/src/filters';
|
||||
import { Connection } from 'libp2p-interfaces/src/topology';
|
||||
|
||||
export const PROTOCOL_NAME = '/fluence/particle/2.0.0';
|
||||
|
||||
/**
|
||||
* Options to configure fluence connection
|
||||
*/
|
||||
export interface FluenceConnectionOptions {
|
||||
/**
|
||||
* Peer id of the Fluence Peer
|
||||
*/
|
||||
peerId: PeerId;
|
||||
|
||||
/**
|
||||
* Multiaddress of the relay to make connection to
|
||||
*/
|
||||
relayAddress: MultiaddrInput;
|
||||
|
||||
/**
|
||||
* The dialing timeout in milliseconds
|
||||
*/
|
||||
dialTimeoutMs?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation for JS peers which connects to Fluence through relay node
|
||||
*/
|
||||
export class RelayConnection extends FluenceConnection {
|
||||
constructor(
|
||||
public peerId: PeerIdB58,
|
||||
private _lib2p2Peer: Lib2p2Peer,
|
||||
private _relayAddress: Multiaddr,
|
||||
public readonly relayPeerId: PeerIdB58,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
private _connection?: Connection;
|
||||
|
||||
static async createConnection(options: FluenceConnectionOptions): Promise<RelayConnection> {
|
||||
const transportKey = Websockets.prototype[Symbol.toStringTag];
|
||||
const lib2p2Peer = await Lib2p2Peer.create({
|
||||
peerId: options.peerId,
|
||||
modules: {
|
||||
transport: [Websockets],
|
||||
streamMuxer: [Mplex],
|
||||
connEncryption: [new Noise()],
|
||||
},
|
||||
config: {
|
||||
transport: {
|
||||
[transportKey]: {
|
||||
filter: allow_all,
|
||||
},
|
||||
},
|
||||
},
|
||||
dialer: {
|
||||
dialTimeout: options?.dialTimeoutMs,
|
||||
},
|
||||
});
|
||||
|
||||
const relayMultiaddr = new Multiaddr(options.relayAddress);
|
||||
const relayPeerId = relayMultiaddr.getPeerId();
|
||||
if (relayPeerId === null) {
|
||||
throw new Error('Specified multiaddr is invalid or missing peer id: ' + options.relayAddress);
|
||||
}
|
||||
|
||||
return new RelayConnection(
|
||||
// force new line
|
||||
options.peerId.toB58String(),
|
||||
lib2p2Peer,
|
||||
relayMultiaddr,
|
||||
relayPeerId,
|
||||
);
|
||||
}
|
||||
|
||||
async disconnect() {
|
||||
await this._lib2p2Peer.unhandle(PROTOCOL_NAME);
|
||||
await this._lib2p2Peer.stop();
|
||||
}
|
||||
|
||||
async sendParticle(nextPeerIds: PeerIdB58[], particle: string): Promise<void> {
|
||||
if (nextPeerIds.length !== 1 && nextPeerIds[0] !== this.relayPeerId) {
|
||||
throw new Error(
|
||||
`Relay connection only accepts peer id of the connected relay. Got: ${JSON.stringify(
|
||||
nextPeerIds,
|
||||
)} instead.`,
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
TODO:: find out why this doesn't work and a new connection has to be established each time
|
||||
if (this._connection.streams.length !== 1) {
|
||||
throw new Error('Incorrect number of streams in FluenceConnection');
|
||||
}
|
||||
|
||||
const sink = this._connection.streams[0].sink;
|
||||
*/
|
||||
|
||||
const conn = await this._lib2p2Peer.dialProtocol(this._relayAddress, PROTOCOL_NAME);
|
||||
const sink = conn.stream.sink;
|
||||
|
||||
pipe(
|
||||
// force new line
|
||||
[Buffer.from(particle, 'utf8')],
|
||||
encode(),
|
||||
sink,
|
||||
);
|
||||
}
|
||||
|
||||
async connect(onIncomingParticle: ParticleHandler) {
|
||||
await this._lib2p2Peer.start();
|
||||
|
||||
this._lib2p2Peer.handle([PROTOCOL_NAME], async ({ connection, stream }) => {
|
||||
pipe(
|
||||
stream.source,
|
||||
// @ts-ignore
|
||||
decode(),
|
||||
async (source: AsyncIterable<string>) => {
|
||||
try {
|
||||
for await (const msg of source) {
|
||||
try {
|
||||
onIncomingParticle(msg);
|
||||
} catch (e) {
|
||||
log.error('error on handling a new incoming message: ' + e);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
log.debug('connection closed: ' + e);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
log.debug(`dialing to the node with client's address: ` + this._lib2p2Peer.peerId.toB58String());
|
||||
|
||||
try {
|
||||
this._connection = await this._lib2p2Peer.dial(this._relayAddress);
|
||||
} catch (e: any) {
|
||||
if (e.name === 'AggregateError' && e._errors?.length === 1) {
|
||||
const error = e._errors[0];
|
||||
throw new Error(`Error dialing node ${this._relayAddress}:\n${error.code}\n${error.message}`);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
14
packages/fluence-connection/tsconfig.json
Normal file
14
packages/fluence-connection/tsconfig.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist/",
|
||||
"lib": ["ES2015"],
|
||||
"target": "ES5",
|
||||
"module": "commonjs",
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"declaration": true,
|
||||
"esModuleInterop": true,
|
||||
},
|
||||
"exclude": ["node_modules", "dist"],
|
||||
"include": ["src/**/*"]
|
||||
}
|
Reference in New Issue
Block a user