/// 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; 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 { 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 { 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(); }); } } class NativeFileUpload implements RequestFileUpload { readonly transfer_key: transfer.UploadKey; private _handle: native.ft.NativeFileTransfer; private _result: Promise; private _result_success: () => any; private _result_error: (error: any) => any; constructor(key: transfer.UploadKey) { this.transfer_key = key; } async put_data(data: BlobPart | File) : Promise { if(this._result) { await this._result; return; } let buffer: native.ft.FileTransferSource; if(data instanceof File) { if(data.size != this.transfer_key.total_size) throw "invalid size"; throw "files arent yet supported"; } else if(typeof(data) === "string") { if(data.length != this.transfer_key.total_size) throw "invalid size"; buffer = native.ft.upload_transfer_object_from_buffer(str2ab8(data)); } else { let buf = data; if(buf.byteLength != this.transfer_key.total_size) throw "invalid size"; if(ArrayBuffer.isView(buf)) buf = buf.buffer.slice(buf.byteOffset); buffer = native.ft.upload_transfer_object_from_buffer(buf); } this._handle = native.ft.spawn_connection({ client_transfer_id: this.transfer_key.client_transfer_id, server_transfer_id: this.transfer_key.server_transfer_id, remote_address: this.transfer_key.peer.hosts[0], remote_port: this.transfer_key.peer.port, transfer_key: this.transfer_key.key, object: buffer }); await (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(); })); } try_put(data: FormData, url: string): Promise { throw "what the hell?"; } } export function spawn_download_transfer(key: transfer.DownloadKey) : transfer.DownloadTransfer { return new NativeFileDownload(key); } export function spawn_upload_transfer(key: transfer.UploadKey) : transfer.NativeFileUpload { return new NativeFileUpload(key); } } Object.assign(window["transfer"] || (window["transfer"] = {} as any), _transfer);