You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
2.7 KiB
TypeScript
111 lines
2.7 KiB
TypeScript
import fetch from 'node-fetch';
|
|
import https from 'https';
|
|
|
|
import { Snode } from './snodePool';
|
|
|
|
import { lokiOnionFetch, SnodeResponse } from './onions';
|
|
|
|
const snodeHttpsAgent = new https.Agent({
|
|
rejectUnauthorized: false,
|
|
});
|
|
|
|
async function lokiPlainFetch(
|
|
url: string,
|
|
fetchOptions: any
|
|
): Promise<boolean | SnodeResponse> {
|
|
const { log } = window;
|
|
|
|
if (url.match(/https:\/\//)) {
|
|
// import that this does not get set in lokiFetch fetchOptions
|
|
fetchOptions.agent = snodeHttpsAgent;
|
|
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
|
} else {
|
|
log.debug('lokirpc:::lokiFetch - http communication', url);
|
|
}
|
|
const response = await fetch(url, fetchOptions);
|
|
// restore TLS checking
|
|
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '1';
|
|
|
|
if (!response.ok) {
|
|
throw new window.textsecure.HTTPError('Loki_rpc error', response);
|
|
}
|
|
const result = await response.text();
|
|
|
|
return {
|
|
body: result,
|
|
status: response.status,
|
|
};
|
|
}
|
|
|
|
interface FetchOptions {
|
|
method: string;
|
|
}
|
|
|
|
// A small wrapper around node-fetch which deserializes response
|
|
// returns nodeFetch response or false
|
|
async function lokiFetch(
|
|
url: string,
|
|
options: FetchOptions,
|
|
targetNode?: Snode
|
|
): Promise<boolean | SnodeResponse> {
|
|
const timeout = 10000;
|
|
const method = options.method || 'GET';
|
|
|
|
const fetchOptions: any = {
|
|
...options,
|
|
timeout,
|
|
method,
|
|
};
|
|
|
|
try {
|
|
// Absence of targetNode indicates that we want a direct connection
|
|
// (e.g. to connect to a seed node for the first time)
|
|
if (window.lokiFeatureFlags.useOnionRequests && targetNode) {
|
|
return await lokiOnionFetch(fetchOptions.body, targetNode);
|
|
}
|
|
|
|
return await lokiPlainFetch(url, fetchOptions);
|
|
} catch (e) {
|
|
if (e.code === 'ENOTFOUND') {
|
|
throw new window.textsecure.NotFoundError('Failed to resolve address', e);
|
|
}
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
// Wrapper for a JSON RPC request
|
|
// Annoyngly, this is used for Lokid requests too
|
|
export async function snodeRpc(
|
|
method: string,
|
|
params: any,
|
|
targetNode: Snode
|
|
): Promise<boolean | SnodeResponse> {
|
|
const url = `https://${targetNode.ip}:${targetNode.port}/storage_rpc/v1`;
|
|
|
|
// TODO: The jsonrpc and body field will be ignored on storage server
|
|
if (params.pubKey) {
|
|
// Ensure we always take a copy
|
|
// tslint:disable-next-line no-parameter-reassignment
|
|
params = {
|
|
...params,
|
|
pubKey: window.getStoragePubKey(params.pubKey),
|
|
};
|
|
}
|
|
const body = {
|
|
jsonrpc: '2.0',
|
|
id: '0',
|
|
method,
|
|
params,
|
|
};
|
|
|
|
const fetchOptions = {
|
|
method: 'POST',
|
|
body: JSON.stringify(body),
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
};
|
|
|
|
return lokiFetch(url, fetchOptions, targetNode);
|
|
}
|