2020-05-14 15:20:39 +03:00
|
|
|
/*
|
2020-05-14 17:30:17 +03:00
|
|
|
* Copyright 2020 Fluence Labs Limited
|
2020-05-14 15:20:39 +03:00
|
|
|
*
|
2020-05-14 17:30:17 +03:00
|
|
|
* 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
|
2020-05-14 15:20:39 +03:00
|
|
|
*
|
2020-05-14 17:30:17 +03:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2020-05-14 15:20:39 +03:00
|
|
|
*
|
2020-05-14 17:30:17 +03:00
|
|
|
* 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.
|
2020-05-14 15:20:39 +03:00
|
|
|
*/
|
|
|
|
|
2020-07-27 16:39:54 +03:00
|
|
|
import {
|
|
|
|
Address,
|
|
|
|
createPeerAddress,
|
|
|
|
createRelayAddress,
|
|
|
|
createProviderAddress,
|
|
|
|
ProtocolType,
|
2020-09-21 16:42:53 +03:00
|
|
|
addressToString, createRelayAddressWithSig
|
2020-07-27 16:39:54 +03:00
|
|
|
} from "./address";
|
2020-08-20 20:28:32 +03:00
|
|
|
import {callToString, FunctionCall, genUUID, makeFunctionCall,} from "./functionCall";
|
2020-05-14 15:20:39 +03:00
|
|
|
import * as PeerId from "peer-id";
|
2020-08-20 20:28:32 +03:00
|
|
|
import {LocalServices} from "./localServices";
|
2020-05-14 15:20:39 +03:00
|
|
|
import Multiaddr from "multiaddr"
|
|
|
|
import {Subscriptions} from "./subscriptions";
|
2020-08-20 20:28:32 +03:00
|
|
|
import {FluenceConnection} from "./fluenceConnection";
|
2020-07-30 15:36:36 +03:00
|
|
|
import {checkInterface, Interface} from "./Interface";
|
2020-08-20 20:28:32 +03:00
|
|
|
import {Service} from "./service";
|
|
|
|
import {Blueprint, checkBlueprint} from "./blueprint";
|
2020-09-15 12:09:13 +03:00
|
|
|
import * as log from 'loglevel';
|
2020-05-14 15:20:39 +03:00
|
|
|
|
2020-07-27 16:39:54 +03:00
|
|
|
/**
|
|
|
|
* @param target receiver
|
|
|
|
* @param args message in the call
|
|
|
|
* @param moduleId module name
|
|
|
|
* @param fname function name
|
|
|
|
* @param name common field for debug purposes
|
|
|
|
* @param msgId hash that will be added to replyTo address
|
|
|
|
*/
|
|
|
|
interface Call {
|
|
|
|
target: Address,
|
|
|
|
args: any,
|
|
|
|
moduleId?: string,
|
|
|
|
fname?: string,
|
|
|
|
msgId?: string,
|
|
|
|
name?: string
|
|
|
|
}
|
|
|
|
|
2020-05-14 15:20:39 +03:00
|
|
|
export class FluenceClient {
|
2020-08-26 18:48:17 +03:00
|
|
|
readonly selfPeerId: PeerId;
|
2020-05-14 15:20:39 +03:00
|
|
|
readonly selfPeerIdStr: string;
|
2020-07-27 16:39:54 +03:00
|
|
|
private nodePeerIdStr: string;
|
2020-05-14 15:20:39 +03:00
|
|
|
|
2020-09-21 16:42:53 +03:00
|
|
|
connection: FluenceConnection;
|
2020-05-14 15:20:39 +03:00
|
|
|
|
2020-08-20 20:28:32 +03:00
|
|
|
private services: LocalServices = new LocalServices();
|
2020-05-14 15:20:39 +03:00
|
|
|
|
|
|
|
private subscriptions: Subscriptions = new Subscriptions();
|
|
|
|
|
2020-08-26 18:48:17 +03:00
|
|
|
constructor(selfPeerId: PeerId) {
|
|
|
|
this.selfPeerId = selfPeerId;
|
|
|
|
this.selfPeerIdStr = selfPeerId.toB58String();
|
2020-05-14 15:20:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Makes call with response from function. Without reply_to field.
|
|
|
|
*/
|
2020-06-12 19:54:09 +03:00
|
|
|
private responseCall(target: Address, args: any): FunctionCall {
|
|
|
|
return makeFunctionCall(genUUID(), target, this.connection.sender, args, undefined, "response");
|
2020-05-14 15:20:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Waits a response that match the predicate.
|
|
|
|
*
|
|
|
|
* @param predicate will be applied to each incoming call until it matches
|
2020-07-27 16:39:54 +03:00
|
|
|
* @param ignoreErrors ignore an errors, wait for success response
|
2020-05-14 15:20:39 +03:00
|
|
|
*/
|
2020-09-21 16:42:53 +03:00
|
|
|
waitResponse(predicate: (args: any, target: Address, replyTo: Address, moduleId?: string, fname?: string) => (boolean | undefined), ignoreErrors: boolean): Promise<any> {
|
2020-07-27 16:39:54 +03:00
|
|
|
return new Promise((resolve, reject) => {
|
2020-05-14 15:20:39 +03:00
|
|
|
// subscribe for responses, to handle response
|
|
|
|
// TODO if there's no conn, reject
|
2020-09-21 16:42:53 +03:00
|
|
|
this.subscribe((args: any, target: Address, replyTo: Address, moduleId?: string, fname?: string) => {
|
|
|
|
if (predicate(args, target, replyTo, moduleId, fname)) {
|
2020-07-27 16:39:54 +03:00
|
|
|
if (args.reason) {
|
|
|
|
if (ignoreErrors) {
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
reject(new Error(args.reason));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
resolve(args);
|
|
|
|
}
|
2020-05-14 15:20:39 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-06-30 16:34:05 +03:00
|
|
|
private getPredicate(msgId: string): (args: any, target: Address) => (boolean | undefined) {
|
2020-07-27 16:39:54 +03:00
|
|
|
return (args: any, target: Address) => target.hash && target.hash === msgId;
|
2020-06-30 16:34:05 +03:00
|
|
|
}
|
|
|
|
|
2020-05-14 15:20:39 +03:00
|
|
|
/**
|
|
|
|
* Send call and forget.
|
|
|
|
*
|
|
|
|
*/
|
2020-07-27 16:39:54 +03:00
|
|
|
async sendCall(call: Call) {
|
2020-05-14 15:20:39 +03:00
|
|
|
if (this.connection && this.connection.isConnected()) {
|
2020-08-20 20:28:32 +03:00
|
|
|
await this.connection.sendFunctionCall(call.target, call.args, call.moduleId, call.fname, call.msgId, call.name);
|
2020-05-14 15:20:39 +03:00
|
|
|
} else {
|
|
|
|
throw Error("client is not connected")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-07-27 16:39:54 +03:00
|
|
|
* Send call to the provider and wait a response matches predicate.
|
2020-05-14 15:20:39 +03:00
|
|
|
*
|
2020-07-27 16:39:54 +03:00
|
|
|
* @param provider published name in dht
|
2020-05-14 15:20:39 +03:00
|
|
|
* @param args message to the service
|
2020-07-27 16:39:54 +03:00
|
|
|
* @param moduleId module name
|
2020-06-29 17:27:53 +03:00
|
|
|
* @param fname function name
|
2020-07-27 16:39:54 +03:00
|
|
|
* @param name debug info
|
2020-05-14 15:20:39 +03:00
|
|
|
*/
|
2020-07-27 16:39:54 +03:00
|
|
|
async callProvider(provider: string, args: any, moduleId?: string, fname?: string, name?: string): Promise<any> {
|
|
|
|
let msgId = genUUID();
|
|
|
|
let predicate = this.getPredicate(msgId);
|
|
|
|
let address = createProviderAddress(provider);
|
|
|
|
await this.sendCall({target: address, args: args, moduleId: moduleId, fname: fname, msgId: msgId, name: name});
|
|
|
|
return await this.waitResponse(predicate, true);
|
2020-06-26 16:12:37 +03:00
|
|
|
}
|
|
|
|
|
2020-09-21 16:42:53 +03:00
|
|
|
/**
|
|
|
|
* Send a message to a client that connected with a relay.
|
|
|
|
*
|
|
|
|
* @param relayId
|
|
|
|
* @param clientId
|
|
|
|
* @param sig
|
|
|
|
* @param moduleId
|
|
|
|
* @param args message to the service
|
|
|
|
* @param fname function name
|
|
|
|
* @param name debug info
|
|
|
|
*/
|
|
|
|
async callClient(relayId: string, clientId: string, sig: string, moduleId: string, args: any, fname?: string, name?: string): Promise<void> {
|
|
|
|
let msgId = genUUID();
|
|
|
|
let clientPeerId = await PeerId.createFromB58String(clientId);
|
|
|
|
let address = await createRelayAddressWithSig(relayId, clientPeerId, sig);
|
|
|
|
|
|
|
|
await this.sendCall({target: address, args: args, moduleId: moduleId, fname: fname, msgId: msgId, name: name})
|
|
|
|
}
|
|
|
|
|
2020-06-26 16:12:37 +03:00
|
|
|
/**
|
2020-07-27 16:39:54 +03:00
|
|
|
* Send a call to the local service and wait a response matches predicate on a peer the client connected with.
|
2020-06-26 16:12:37 +03:00
|
|
|
*
|
2020-06-29 17:27:53 +03:00
|
|
|
* @param moduleId
|
2020-07-27 16:39:54 +03:00
|
|
|
* @param addr node address
|
2020-06-26 16:12:37 +03:00
|
|
|
* @param args message to the service
|
2020-06-29 17:27:53 +03:00
|
|
|
* @param fname function name
|
2020-07-27 16:39:54 +03:00
|
|
|
* @param name debug info
|
2020-06-26 16:12:37 +03:00
|
|
|
*/
|
2020-08-20 20:28:32 +03:00
|
|
|
async callPeer(moduleId: string, args: any, fname?: string, addr?: string, name?: string): Promise<any> {
|
2020-07-27 16:39:54 +03:00
|
|
|
let msgId = genUUID();
|
|
|
|
let predicate = this.getPredicate(msgId);
|
|
|
|
|
|
|
|
let address;
|
|
|
|
if (addr) {
|
|
|
|
address = createPeerAddress(addr);
|
2020-05-14 15:20:39 +03:00
|
|
|
} else {
|
2020-07-27 16:39:54 +03:00
|
|
|
address = createPeerAddress(this.nodePeerIdStr);
|
2020-05-14 15:20:39 +03:00
|
|
|
}
|
|
|
|
|
2020-08-20 20:28:32 +03:00
|
|
|
await this.sendCall({target: address, args: args, moduleId: moduleId, fname: fname, msgId: msgId, name: name})
|
2020-07-27 16:39:54 +03:00
|
|
|
|
|
|
|
return await this.waitResponse(predicate, false);
|
2020-05-14 15:20:39 +03:00
|
|
|
}
|
|
|
|
|
2020-07-27 16:39:54 +03:00
|
|
|
async callService(peerId: string, serviceId: string, moduleId: string, args: any, fname?: string): Promise<any> {
|
|
|
|
let target = createPeerAddress(peerId, serviceId);
|
|
|
|
let msgId = genUUID();
|
|
|
|
let predicate = this.getPredicate(msgId);
|
|
|
|
|
|
|
|
await this.sendCall({target: target, args: args, moduleId: moduleId, fname: fname, msgId: msgId});
|
|
|
|
return await this.waitResponse(predicate, false);
|
2020-06-26 16:12:37 +03:00
|
|
|
}
|
|
|
|
|
2020-08-20 20:28:32 +03:00
|
|
|
getService(peerId: string, serviceId: string): Service {
|
|
|
|
return new Service(this, peerId, serviceId);
|
|
|
|
}
|
|
|
|
|
2020-05-14 15:20:39 +03:00
|
|
|
/**
|
|
|
|
* Handle incoming call.
|
|
|
|
* If FunctionCall returns - we should send it as a response.
|
|
|
|
*/
|
|
|
|
handleCall(): (call: FunctionCall) => FunctionCall | undefined {
|
|
|
|
|
|
|
|
let _this = this;
|
|
|
|
|
|
|
|
return (call: FunctionCall) => {
|
2020-09-15 12:09:13 +03:00
|
|
|
log.debug("FunctionCall received:");
|
2020-05-14 15:20:39 +03:00
|
|
|
|
|
|
|
// if other side return an error - handle it
|
|
|
|
// TODO do it in the protocol
|
|
|
|
/*if (call.arguments.error) {
|
|
|
|
this.handleError(call);
|
|
|
|
} else {
|
|
|
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
let target = call.target;
|
|
|
|
|
|
|
|
// the tail of addresses should be you or your service
|
|
|
|
let lastProtocol = target.protocols[target.protocols.length - 1];
|
|
|
|
|
|
|
|
// call all subscriptions for a new call
|
|
|
|
_this.subscriptions.applyToSubscriptions(call);
|
|
|
|
|
|
|
|
switch (lastProtocol.protocol) {
|
2020-06-26 16:12:37 +03:00
|
|
|
case ProtocolType.Providers:
|
|
|
|
|
2020-05-14 15:20:39 +03:00
|
|
|
|
|
|
|
return undefined;
|
|
|
|
case ProtocolType.Client:
|
|
|
|
if (lastProtocol.value === _this.selfPeerIdStr) {
|
2020-09-15 12:09:13 +03:00
|
|
|
log.debug(`relay call:`);
|
|
|
|
log.debug(JSON.stringify(call, undefined, 2));
|
2020-06-26 16:12:37 +03:00
|
|
|
if (call.module) {
|
|
|
|
try {
|
|
|
|
// call of the service, service should handle response sending, error handling, requests to other services
|
|
|
|
let applied = _this.services.applyToService(call);
|
|
|
|
|
|
|
|
// if the request hasn't been applied, there is no such service. Return an error.
|
|
|
|
if (!applied) {
|
2020-09-15 12:09:13 +03:00
|
|
|
log.warn(`there is no service ${lastProtocol.value}`);
|
2020-06-26 16:12:37 +03:00
|
|
|
return this.responseCall(call.reply_to, {
|
|
|
|
reason: `there is no such service`,
|
|
|
|
msg: call
|
|
|
|
});
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
// if service throw an error, return it to the sender
|
|
|
|
return this.responseCall(call.reply_to, {
|
|
|
|
reason: `error on execution: ${e}`,
|
|
|
|
msg: call
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2020-05-14 15:20:39 +03:00
|
|
|
} else {
|
2020-09-15 12:09:13 +03:00
|
|
|
log.warn(`this relay call is not for me: ${callToString(call)}`);
|
2020-06-12 19:54:09 +03:00
|
|
|
return this.responseCall(call.reply_to, {
|
2020-05-25 19:49:13 +03:00
|
|
|
reason: `this relay call is not for me`,
|
|
|
|
msg: call
|
|
|
|
});
|
2020-05-14 15:20:39 +03:00
|
|
|
}
|
|
|
|
return undefined;
|
|
|
|
case ProtocolType.Peer:
|
|
|
|
if (lastProtocol.value === this.selfPeerIdStr) {
|
2020-09-15 12:09:13 +03:00
|
|
|
log.debug(`peer call: ${call}`);
|
2020-05-14 15:20:39 +03:00
|
|
|
} else {
|
2020-09-15 12:09:13 +03:00
|
|
|
log.warn(`this peer call is not for me: ${callToString(call)}`);
|
2020-06-12 19:54:09 +03:00
|
|
|
return this.responseCall(call.reply_to, {
|
2020-05-25 19:49:13 +03:00
|
|
|
reason: `this relay call is not for me`,
|
|
|
|
msg: call
|
|
|
|
});
|
2020-05-14 15:20:39 +03:00
|
|
|
}
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2020-07-27 16:39:54 +03:00
|
|
|
* Become a name provider. Other network members could find and call one of the providers of this name by this name.
|
2020-05-14 15:20:39 +03:00
|
|
|
*/
|
2020-07-27 16:39:54 +03:00
|
|
|
async provideName(name: string, fn: (req: FunctionCall) => void) {
|
|
|
|
let replyTo = this.connection.sender;
|
|
|
|
await this.callPeer("provide", {name: name, address: addressToString(replyTo)})
|
|
|
|
|
|
|
|
this.services.addService(name, fn);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sends a call to create a service on remote node.
|
|
|
|
*/
|
2020-09-15 12:09:13 +03:00
|
|
|
async createService(blueprint: string, peerId?: string): Promise<string> {
|
2020-08-20 20:28:32 +03:00
|
|
|
let resp = await this.callPeer("create", {blueprint_id: blueprint}, undefined, peerId);
|
2020-07-27 16:39:54 +03:00
|
|
|
|
2020-08-20 20:28:32 +03:00
|
|
|
if (resp && resp.service_id) {
|
|
|
|
return resp.service_id
|
2020-07-27 16:39:54 +03:00
|
|
|
} else {
|
2020-09-15 12:09:13 +03:00
|
|
|
log.error("Unknown response type on `createService`: ", resp)
|
2020-07-27 16:39:54 +03:00
|
|
|
throw new Error("Unknown response type on `createService`");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-15 12:09:13 +03:00
|
|
|
async addBlueprint(name: string, dependencies: string[], peerId?: string): Promise<string> {
|
2020-08-20 20:28:32 +03:00
|
|
|
|
|
|
|
let id = genUUID();
|
|
|
|
let blueprint = {
|
|
|
|
name: name,
|
|
|
|
id: id,
|
|
|
|
dependencies: dependencies
|
|
|
|
};
|
|
|
|
let msg_id = genUUID();
|
|
|
|
|
|
|
|
await this.callPeer("add_blueprint", {msg_id, blueprint}, undefined, peerId);
|
|
|
|
|
|
|
|
return id;
|
|
|
|
}
|
|
|
|
|
2020-07-30 15:36:36 +03:00
|
|
|
async getInterface(serviceId: string, peerId?: string): Promise<Interface> {
|
2020-07-27 16:39:54 +03:00
|
|
|
let resp;
|
|
|
|
resp = await this.callPeer("get_interface", {service_id: serviceId}, undefined, peerId)
|
2020-07-30 15:36:36 +03:00
|
|
|
let i = resp.interface;
|
|
|
|
|
|
|
|
if (checkInterface(i)) {
|
|
|
|
return i;
|
|
|
|
} else {
|
|
|
|
throw new Error("Unexpected");
|
|
|
|
}
|
2020-07-27 16:39:54 +03:00
|
|
|
}
|
|
|
|
|
2020-08-20 20:28:32 +03:00
|
|
|
async getAvailableBlueprints(peerId?: string): Promise<Blueprint[]> {
|
2020-08-26 18:48:17 +03:00
|
|
|
let resp = await this.callPeer("get_available_blueprints", {}, undefined, peerId);
|
2020-08-20 20:28:32 +03:00
|
|
|
|
|
|
|
let blueprints = resp.available_blueprints;
|
|
|
|
|
|
|
|
if (blueprints && blueprints instanceof Array) {
|
|
|
|
return blueprints.map((b: any) => {
|
|
|
|
if (checkBlueprint(b)) {
|
|
|
|
return b;
|
|
|
|
} else {
|
|
|
|
throw new Error("Unexpected");
|
|
|
|
}
|
|
|
|
});
|
2020-07-27 16:39:54 +03:00
|
|
|
} else {
|
2020-08-20 20:28:32 +03:00
|
|
|
throw new Error("Unexpected. 'get_active_interfaces' should return an array of interfaces.");
|
2020-07-27 16:39:54 +03:00
|
|
|
}
|
2020-08-20 20:28:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
async getActiveInterfaces(peerId?: string): Promise<Interface[]> {
|
2020-08-26 18:48:17 +03:00
|
|
|
let resp = await this.callPeer("get_active_interfaces", {}, undefined, peerId);
|
2020-08-20 20:28:32 +03:00
|
|
|
|
2020-07-30 15:36:36 +03:00
|
|
|
let interfaces = resp.active_interfaces;
|
|
|
|
if (interfaces && interfaces instanceof Array) {
|
|
|
|
return interfaces.map((i: any) => {
|
|
|
|
if (checkInterface(i)) {
|
|
|
|
return i;
|
|
|
|
} else {
|
|
|
|
throw new Error("Unexpected");
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
2020-08-20 20:28:32 +03:00
|
|
|
throw new Error("Unexpected. 'get_active_interfaces' should return an array pf interfaces.");
|
2020-07-30 15:36:36 +03:00
|
|
|
}
|
2020-07-27 16:39:54 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
async getAvailableModules(peerId?: string): Promise<string[]> {
|
2020-08-20 20:28:32 +03:00
|
|
|
let resp = await this.callPeer("get_available_modules", {}, undefined, peerId);
|
2020-07-27 16:39:54 +03:00
|
|
|
return resp.available_modules;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add new WASM module to the node.
|
|
|
|
*
|
|
|
|
* @param bytes WASM in base64
|
|
|
|
* @param name WASM identificator
|
|
|
|
* @param mem_pages_count memory amount for WASM
|
|
|
|
* @param envs environment variables
|
|
|
|
* @param mapped_dirs links to directories
|
|
|
|
* @param preopened_files files and directories that will be used in WASM
|
|
|
|
* @param peerId the node to add module
|
|
|
|
*/
|
|
|
|
async addModule(bytes: string, name: string, mem_pages_count: number, envs: string[], mapped_dirs: any, preopened_files: string[], peerId?: string): Promise<any> {
|
|
|
|
let config: any = {
|
|
|
|
logger_enabled: true,
|
|
|
|
mem_pages_count: mem_pages_count,
|
|
|
|
name: name,
|
|
|
|
wasi: {
|
|
|
|
envs: envs,
|
|
|
|
mapped_dirs: mapped_dirs,
|
|
|
|
preopened_files: preopened_files
|
|
|
|
}
|
|
|
|
}
|
2020-08-20 20:28:32 +03:00
|
|
|
let resp = await this.callPeer("add_module", {bytes: bytes, config: config}, undefined, peerId);
|
2020-05-14 15:20:39 +03:00
|
|
|
|
2020-07-27 16:39:54 +03:00
|
|
|
return resp.available_modules;
|
2020-05-14 15:20:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// subscribe new hook for every incoming call, to handle in-service responses and other different cases
|
|
|
|
// the hook will be deleted if it will return `true`
|
2020-09-21 16:42:53 +03:00
|
|
|
subscribe(predicate: (args: any, target: Address, replyTo: Address, moduleId?: string, fname?: string) => (boolean | undefined)) {
|
2020-05-14 15:20:39 +03:00
|
|
|
this.subscriptions.subscribe(predicate)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2020-06-29 17:27:53 +03:00
|
|
|
* Sends a call to unregister the service.
|
2020-05-14 15:20:39 +03:00
|
|
|
*/
|
2020-06-29 17:27:53 +03:00
|
|
|
async unregisterService(moduleId: string) {
|
|
|
|
if (this.services.deleteService(moduleId)) {
|
2020-09-15 12:09:13 +03:00
|
|
|
log.warn("unregister is not implemented yet (service: ${serviceId}")
|
2020-05-14 15:20:39 +03:00
|
|
|
// TODO unregister in fluence network when it will be supported
|
|
|
|
// let regMsg = makeRegisterMessage(serviceId, PeerId.createFromB58String(this.nodePeerId));
|
|
|
|
// await this.sendFunctionCall(regMsg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-28 20:19:26 +03:00
|
|
|
async disconnect(): Promise<void> {
|
|
|
|
return this.connection.disconnect();
|
|
|
|
}
|
|
|
|
|
2020-05-14 15:20:39 +03:00
|
|
|
/**
|
|
|
|
* Establish a connection to the node. If the connection is already established, disconnect and reregister all services in a new connection.
|
|
|
|
*
|
|
|
|
* @param multiaddr
|
|
|
|
*/
|
|
|
|
async connect(multiaddr: string | Multiaddr): Promise<void> {
|
|
|
|
|
|
|
|
multiaddr = Multiaddr(multiaddr);
|
|
|
|
|
|
|
|
let nodePeerId = multiaddr.getPeerId();
|
2020-07-27 16:39:54 +03:00
|
|
|
this.nodePeerIdStr = nodePeerId;
|
2020-05-14 15:20:39 +03:00
|
|
|
|
|
|
|
if (!nodePeerId) {
|
|
|
|
throw Error("'multiaddr' did not contain a valid peer id")
|
|
|
|
}
|
|
|
|
|
|
|
|
let firstConnection: boolean = true;
|
|
|
|
if (this.connection) {
|
|
|
|
firstConnection = false;
|
|
|
|
await this.connection.disconnect();
|
|
|
|
}
|
|
|
|
|
|
|
|
let peerId = PeerId.createFromB58String(nodePeerId);
|
2020-09-21 16:42:53 +03:00
|
|
|
let sender = await createRelayAddress(nodePeerId, this.selfPeerId, false);
|
|
|
|
let replyTo = await createRelayAddress(nodePeerId, this.selfPeerId, true);
|
|
|
|
let connection = new FluenceConnection(multiaddr, peerId, this.selfPeerId, sender, replyTo, this.handleCall());
|
2020-05-14 15:20:39 +03:00
|
|
|
|
|
|
|
await connection.connect();
|
|
|
|
|
|
|
|
this.connection = connection;
|
|
|
|
|
|
|
|
// if the client already had a connection, it will reregister all services after establishing a new connection.
|
|
|
|
if (!firstConnection) {
|
|
|
|
for (let service of this.services.getAllServices().keys()) {
|
2020-07-27 16:39:54 +03:00
|
|
|
await this.connection.provideName(service);
|
2020-05-14 15:20:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|