Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/webtorrent/webtorrent.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCas <6506529+ThaUnknown@users.noreply.github.com>2021-08-20 00:41:34 +0300
committerGitHub <noreply@github.com>2021-08-20 00:41:34 +0300
commit604943e325c68721251a71c29d94e6a07ce0b31c (patch)
treed6728521ed5d4f13e5a3484f7d670756e89a832b /index.js
parenta46a7a51d9fd8efef86533c5868a2d23b1346b6e (diff)
feat: add service worker server as an alternative to renderMedia (#2098)
* feat: add service worker server as an alternative to renderMedia * code QL * thanks gh auto merge Co-authored-by: Diego Rodríguez Baquero <github@diegorbaquero.com>
Diffstat (limited to 'index.js')
-rw-r--r--index.js69
1 files changed, 68 insertions, 1 deletions
diff --git a/index.js b/index.js
index 8866665..ec516a0 100644
--- a/index.js
+++ b/index.js
@@ -1,5 +1,6 @@
/*! webtorrent. MIT License. WebTorrent LLC <https://webtorrent.io/opensource> */
-/* global FileList */
+/* global FileList, ServiceWorker */
+/* eslint-env browser */
const { EventEmitter } = require('events')
const concat = require('simple-concat')
@@ -81,6 +82,10 @@ class WebTorrent extends EventEmitter {
this._downloadLimit = Math.max((typeof opts.downloadLimit === 'number') ? opts.downloadLimit : -1, -1)
this._uploadLimit = Math.max((typeof opts.uploadLimit === 'number') ? opts.uploadLimit : -1, -1)
+ this.serviceWorker = null
+ this.workerKeepAliveInterval = null
+ this.workerPortCount = 0
+
if (opts.secure === true) {
require('./lib/peer').enableSecure()
}
@@ -157,6 +162,68 @@ class WebTorrent extends EventEmitter {
}
}
+ /**
+ * Accepts an existing service worker registration [navigator.serviceWorker.controller]
+ * which must be activated, "creates" a file server for streamed file rendering to use.
+ *
+ * @param {ServiceWorker} controller
+ * @param {function=} cb
+ * @return {null}
+ */
+ loadWorker (controller, cb = () => {}) {
+ if (!(controller instanceof ServiceWorker)) throw new Error('Invalid worker registration')
+ if (controller.state !== 'activated') throw new Error('Worker isn\'t activated')
+ const keepAliveTime = 20000
+
+ this.serviceWorker = controller
+
+ navigator.serviceWorker.addEventListener('message', event => {
+ const { data } = event
+ if (!data.type || !data.type === 'webtorrent' || !data.url) return null
+ let [infoHash, ...filePath] = data.url.slice(data.url.indexOf(data.scope + 'webtorrent/') + 11 + data.scope.length).split('/')
+ filePath = decodeURI(filePath.join('/'))
+ if (!infoHash || !filePath) return null
+
+ const [port] = event.ports
+
+ const file = this.get(infoHash) && this.get(infoHash).files.find(file => file.path === filePath)
+ if (!file) return null
+
+ const [response, stream, raw] = file._serve(data)
+ const asyncIterator = stream && stream[Symbol.asyncIterator]()
+
+ const cleanup = () => {
+ port.onmessage = null
+ if (stream) stream.destroy()
+ if (raw) raw.destroy()
+ this.workerPortCount--
+ if (!this.workerPortCount) {
+ clearInterval(this.workerKeepAliveInterval)
+ this.workerKeepAliveInterval = null
+ }
+ }
+
+ port.onmessage = async msg => {
+ if (msg.data) {
+ let chunk
+ try {
+ chunk = (await asyncIterator.next()).value
+ } catch (e) {
+ // chunk is yet to be downloaded or it somehow failed, should this be logged?
+ }
+ port.postMessage(chunk)
+ if (!chunk) cleanup()
+ if (!this.workerKeepAliveInterval) this.workerKeepAliveInterval = setInterval(() => fetch(`${this.serviceWorker.scriptURL.substr(0, this.serviceWorker.scriptURL.lastIndexOf('/') + 1).slice(window.location.origin.length)}webtorrent/keepalive/`), keepAliveTime)
+ } else {
+ cleanup()
+ }
+ }
+ this.workerPortCount++
+ port.postMessage(response)
+ })
+ cb(this.serviceWorker)
+ }
+
get downloadSpeed () { return this._downloadSpeed() }
get uploadSpeed () { return this._uploadSpeed() }