TeaSpeak-Client/modules/renderer/connection/FileTransfer.ts
2019-08-21 10:00:27 +02:00

97 lines
3.1 KiB
TypeScript

/// <reference path="../imports/imports_shared.d.ts" />
window["require_setup"](module);
import * as native from "teaclient_connection";
namespace _transfer {
class NativeFileDownload implements transfer.DownloadTransfer {
readonly key: transfer.DownloadKey;
private _handle: native.ft.NativeFileTransfer;
private _buffer: Uint8Array;
private _result: Promise<void>;
private _response: Response;
private _result_success: () => any;
private _result_error: (error: any) => any;
constructor(key: transfer.DownloadKey) {
this.key = key;
this._buffer = new Uint8Array(key.total_size);
this._handle = native.ft.spawn_connection({
client_transfer_id: key.client_transfer_id,
server_transfer_id: key.server_transfer_id,
remote_address: key.peer.hosts[0],
remote_port: key.peer.port,
transfer_key: key.key,
object: native.ft.download_transfer_object_from_buffer(this._buffer.buffer)
});
}
get_key(): transfer.DownloadKey {
return this.key;
}
async request_file(): Promise<Response> {
if(this._response)
return this._response;
try {
await (this._result || this._start_transfer());
} catch(error) {
throw error;
}
if(this._response)
return this._response;
const buffer = this._buffer.buffer.slice(this._buffer.byteOffset, this._buffer.byteOffset + Math.min(64, this._buffer.byteLength));
/* may another task has been stepped by and already set the response */
return this._response || (this._response = new Response(this._buffer, {
status: 200,
statusText: "success",
headers: {
"X-media-bytes": base64_encode_ab(buffer)
}
}));
}
_start_transfer() : Promise<void> {
return this._result = new Promise((resolve, reject) => {
this._result_error = (error) => {
this._result_error = undefined;
this._result_success = undefined;
reject(error);
};
this._result_success = () => {
this._result_error = undefined;
this._result_success = undefined;
resolve();
};
this._handle.callback_failed = this._result_error;
this._handle.callback_finished = aborted => {
if(aborted)
this._result_error("aborted");
else
this._result_success();
};
this._handle.start();
});
}
}
export function spawn_download_transfer(key: transfer.DownloadKey) : transfer.DownloadTransfer {
return new NativeFileDownload(key);
}
}
Object.assign(window["transfer"] || (window["transfer"] = {}), _transfer);