-
-
Notifications
You must be signed in to change notification settings - Fork 267
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(request-manager): support external Tor
- Loading branch information
Showing
5 changed files
with
173 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import { EventEmitter } from 'events'; | ||
import { waitUntil } from './utils'; | ||
|
||
import { checkSocks5Proxy } from '@trezor/node-utils'; | ||
|
||
import { TOR_CONTROLLER_STATUS, TorControllerStatus, TorExternalConnectionOptions } from './types'; | ||
|
||
const WAITING_TIME = 1_000; | ||
const MAX_TRIES_WAITING = 200; | ||
|
||
export class TorControllerExternal extends EventEmitter { | ||
status: TorControllerStatus = TOR_CONTROLLER_STATUS.Stopped; | ||
options: TorExternalConnectionOptions; | ||
|
||
constructor(options: TorExternalConnectionOptions) { | ||
super(); | ||
this.options = options; | ||
} | ||
|
||
private getIsStopped() { | ||
return this.status === TOR_CONTROLLER_STATUS.Stopped; | ||
} | ||
|
||
private async getIsExternalTorRunning() { | ||
let isSocks5ProxyPort = false; | ||
try { | ||
isSocks5ProxyPort = await checkSocks5Proxy(this.options.host, this.options.port); | ||
} catch { | ||
// Ignore errors. | ||
} | ||
|
||
return isSocks5ProxyPort; | ||
} | ||
|
||
private startBootstrap() { | ||
this.status = TOR_CONTROLLER_STATUS.Bootstrapping; | ||
} | ||
|
||
private successfullyBootstrapped() { | ||
this.status = TOR_CONTROLLER_STATUS.ExternalTorRunning; | ||
} | ||
|
||
public getTorConfiguration() { | ||
return ''; | ||
} | ||
|
||
public async waitUntilAlive() { | ||
this.startBootstrap(); | ||
await waitUntil( | ||
MAX_TRIES_WAITING, | ||
WAITING_TIME, | ||
async () => { | ||
const isRunning = await this.getIsExternalTorRunning(); | ||
if (isRunning) { | ||
// this.status = TOR_CONTROLLER_STATUS.ExternalTorRunning; | ||
this.successfullyBootstrapped(); | ||
} | ||
|
||
return isRunning; | ||
}, | ||
() => { | ||
return this.getIsStopped(); | ||
}, | ||
); | ||
} | ||
|
||
public async getStatus() { | ||
const isExternalTorRunning = await this.getIsExternalTorRunning(); | ||
|
||
return new Promise(resolve => { | ||
if (isExternalTorRunning) { | ||
return resolve(TOR_CONTROLLER_STATUS.ExternalTorRunning); | ||
} | ||
|
||
return resolve(TOR_CONTROLLER_STATUS.Stopped); | ||
}); | ||
} | ||
|
||
public closeActiveCircuits() { | ||
// Do nothing. Not possible in External Tor without ControlPort. | ||
} | ||
|
||
public stop() { | ||
this.status = TOR_CONTROLLER_STATUS.Stopped; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { createTimeoutPromise } from '@trezor/utils'; | ||
|
||
export const waitUntil = ( | ||
MAX_TRIES_WAITING: number, | ||
WAITING_TIME: number, | ||
checkToSuccess: () => Promise<boolean>, | ||
getIsStopped: () => boolean, | ||
): Promise<void> => { | ||
const errorMessages: string[] = []; | ||
|
||
const waitUntilResponse = async (triesCount: number): Promise<void> => { | ||
if (getIsStopped()) { | ||
// If stopped we do not wait anymore. | ||
return; | ||
} | ||
if (triesCount >= MAX_TRIES_WAITING) { | ||
throw new Error(`Timeout waiting: \n${errorMessages.join('\n')}`); | ||
} | ||
try { | ||
const completed = await checkToSuccess(); | ||
if (completed) { | ||
return; | ||
} | ||
} catch (error) { | ||
// Some error here is expected when waiting but | ||
// we do not want to throw until MAX_TRIES_WAITING is reach. | ||
// Instead we want to log it to know what causes the error. | ||
if (error && error.message) { | ||
console.warn('error:', error.message); | ||
errorMessages.push(error.message); | ||
} | ||
} | ||
await createTimeoutPromise(WAITING_TIME); | ||
|
||
return waitUntilResponse(triesCount + 1); | ||
}; | ||
|
||
return waitUntilResponse(1); | ||
}; |