import ipc from "node-ipc";
|
|
import { Socket } from "net";
|
|
import { ISerializedTorrent, ITorrent } from "../common";
|
|
|
|
interface IResponse {
|
|
response?: any,
|
|
error?: string | Error
|
|
}
|
|
|
|
export default class TorrentClientIpc
|
|
{
|
|
/**
|
|
* Indicate if there is an active connection to the IPC
|
|
*/
|
|
private __isConnected: boolean;
|
|
|
|
/**
|
|
* The active IPC socket
|
|
*/
|
|
protected socket!: Socket;
|
|
|
|
/**
|
|
* Create a new IPC client for the torrent client
|
|
*/
|
|
constructor() {
|
|
ipc.config.id = "torrent_webui";
|
|
ipc.config.retry = 1500;
|
|
ipc.config.silent = true;
|
|
|
|
this.__isConnected = false;
|
|
}
|
|
|
|
/**
|
|
* Boot the torrent client IPC service
|
|
*/
|
|
public boot() {
|
|
return new Promise<void>((resolve, reject) => {
|
|
console.log(process.env["TORRENT_CLIENT_IPC_SOCKET"]);
|
|
ipc.connectTo("torrent_client", process.env["TORRENT_CLIENT_IPC_SOCKET"], () => {
|
|
this.socket = ipc.of["torrent_client"];
|
|
this.installSocketEventHandlers(this.socket);
|
|
this.installSocketMessageHandlers(this.socket);
|
|
resolve();
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Install the event handlers for the IPC socket
|
|
*/
|
|
protected installSocketEventHandlers(socket: Socket) {
|
|
socket.on("connect", () => this.onConnect());
|
|
socket.on("error", (error: any) => this.onError(error));
|
|
socket.on("disconnect", () => this.onDisconnect());
|
|
socket.on("destroy", () => this.onDestroy());
|
|
}
|
|
|
|
protected installSocketMessageHandlers(socket: Socket) {
|
|
}
|
|
|
|
// Socket Event Handlers -----------------------------------------------------------------------
|
|
|
|
protected onConnect() {
|
|
if (!this.__isConnected) {
|
|
console.log("IPC: Connection established");
|
|
}
|
|
this.__isConnected = true;
|
|
}
|
|
|
|
protected onError(error: string | Error) {
|
|
if (this.__isConnected) {
|
|
console.log("IPC: Error occurred:", error);
|
|
}
|
|
}
|
|
|
|
protected onDisconnect() {
|
|
if (this.__isConnected) {
|
|
console.log("IPC: Disconnected");
|
|
}
|
|
this.__isConnected = false;
|
|
}
|
|
|
|
protected onDestroy() {
|
|
console.log("IPC: Destroyed");
|
|
}
|
|
|
|
// Methods -------------------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Perform a general request to the torrent client
|
|
*/
|
|
protected async request(method: string, ...message: any[]) {
|
|
return new Promise<IResponse>((resolve, reject) => {
|
|
if (!this.isConnected) {
|
|
throw new Error("Not connected to torrent client");
|
|
}
|
|
let respond = (response: any) => {
|
|
clearTimeout(timeout);
|
|
resolve(response);
|
|
}
|
|
// Include timeout mechanism in the off chance something breaks
|
|
let timeout = setTimeout(() => {
|
|
this.socket.off(method, respond);
|
|
reject("Torrent client IPC request timeout")
|
|
}, 1000);
|
|
this.socket.once(method, respond);
|
|
this.socket.emit(method, message);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Add a torrent to the client
|
|
* @param torrent Magnet URI or file buffer
|
|
*/
|
|
public async add(torrent: string | Buffer) {
|
|
let response = await this.request("add", torrent);
|
|
if (response.error) {
|
|
throw new Error("Failed to add torrent");
|
|
}
|
|
return <string>response.response;
|
|
}
|
|
|
|
/**
|
|
* Remove a torrent from the client
|
|
* @param torrent Torrent info hash
|
|
*/
|
|
public async remove(torrent: string) {
|
|
let response = await this.request("remove", torrent);
|
|
if (response.error) {
|
|
throw new Error("Failed to remove torrent");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get a list of all torrents in the client
|
|
*/
|
|
public async list() {
|
|
let response = await this.request("list");
|
|
if (response.error) {
|
|
console.error(response.error);
|
|
throw new Error("Failed to obtain torrent list");
|
|
}
|
|
console.log("Response is:", response);
|
|
return <ITorrent[]>response.response;
|
|
}
|
|
|
|
/**
|
|
* Get full details of each of the provided torrents
|
|
* @param torrentIds Array of torrent info hashes
|
|
*/
|
|
public async details(...torrentIds: string[]) {
|
|
let response = await this.request("details", torrentIds);
|
|
if (response.error) {
|
|
console.error(response.error);
|
|
throw new Error("Failed to retrieve torrent details");
|
|
}
|
|
return <ISerializedTorrent[]>response.response;
|
|
}
|
|
|
|
// Accessors -----------------------------------------------------------------------------------
|
|
|
|
get isConnected() {
|
|
return this.__isConnected;
|
|
}
|
|
}
|