summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Morrow <victor.j.morrow@gmail.com>2018-12-27 13:17:01 -0500
committerGitHub <noreply@github.com>2018-12-27 13:17:01 -0500
commite5b19e7f895a9865b276433c939ff932d14a93ce (patch)
treefee9bd5cfc9f60409aa49914902d202e4a164508
parent9e24e52d2ce849c338c61c9067e9459b495ca101 (diff)
parent8eca65c71fe968718a7b49b058ad89e117c1b751 (diff)
Merge pull request #11 from vijayee/masterHEADv0.1.0master
Various Bug Fixes
-rw-r--r--Dockerfile6
-rw-r--r--package-lock.json18
-rw-r--r--package.json9
-rw-r--r--src/block-cache-cluster.js67
-rw-r--r--src/block-router.js77
-rw-r--r--src/command.js2
-rw-r--r--src/config.js11
-rw-r--r--src/electron/views/export/export.vue57
-rw-r--r--src/electron/views/export/index.html1
-rw-r--r--src/electron/views/export/index.js65
-rw-r--r--src/electron/views/update/update.vue2
-rw-r--r--src/exporter.js38
-rw-r--r--src/index.js53
-rw-r--r--src/node.js3
-rw-r--r--src/scheduler.js50
15 files changed, 260 insertions, 199 deletions
diff --git a/Dockerfile b/Dockerfile
index 83f371d..cc37414 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,16 +1,16 @@
FROM ubuntu:bionic
-COPY ["./dist/OFF System_0.0.2_amd64.deb", "./"]
+COPY ["./dist/OFF_System_0.1.0_linux_amd64.deb", "./"]
EXPOSE 23402
EXPOSE 8200
ENV LD_LIBRARY_PATH="/usr/local/lib"
RUN apt-get update
RUN apt install libasound2 -y
-RUN apt install "./OFF System_0.0.2_amd64.deb" -f -y
+RUN apt install "./OFF_System_0.1.0_linux_amd64.deb" -f -y
RUN apt-get update -y && \
apt-get install -y libgtk2.0-0 && \
apt-get install -y libnotify-dev && \
apt-get install -y libgconf-2-4 && \
apt-get install -y libnss3
ENV ELECTRON_RUN_AS_NODE="true"
-ENTRYPOINT [ "offs", "/opt/OFF System/resources/app.asar/src/index.js"] \ No newline at end of file
+ENTRYPOINT [ "offs", "/opt/offs/resources/app.asar/src/index.js", "--path", "/offs"] \ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 7ff7639..3139b25 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "js-offs",
- "version": "0.0.91",
+ "version": "0.1.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -11,9 +11,9 @@
"dev": true
},
"@types/node": {
- "version": "8.10.38",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.38.tgz",
- "integrity": "sha512-EibsnbJerd0hBFaDjJStFrVbVBAtOy4dgL8zZFw0uOvPqzBAX59Ci8cgjg3+RgJIWhsB5A4c+pi+D4P9tQQh/A==",
+ "version": "8.10.39",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.39.tgz",
+ "integrity": "sha512-rE7fktr02J8ybFf6eysife+WF+L4sAHWzw09DgdCebEu+qDwMvv4zl6Bc+825ttGZP73kCKxa3dhJOoGJ8+5mA==",
"dev": true
},
"JSONStream": {
@@ -6016,6 +6016,11 @@
"integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=",
"dev": true
},
+ "pretty-bytes": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.1.0.tgz",
+ "integrity": "sha512-wa5+qGVg9Yt7PB6rYm3kXlKzgzgivYTLRandezh43jjRqgyDyP+9YxfJpJiLs9yKD1WeU8/OvtToWpW7255FtA=="
+ },
"private": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/private/-/private-0.1.7.tgz",
@@ -7015,6 +7020,11 @@
"resolved": "https://registry.npmjs.org/streamifier/-/streamifier-0.1.1.tgz",
"integrity": "sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8="
},
+ "streamspeed": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/streamspeed/-/streamspeed-1.1.1.tgz",
+ "integrity": "sha512-8nb1BJLXtBkFB4quAzusUFAl67QnIjKAQo8Qdzn4qRJVyASrMLuaXQhnzyi7WhjZySQFy+JXqSFzaEY307hxHQ=="
+ },
"strict-uri-encode": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
diff --git a/package.json b/package.json
index 8e58b59..deb0972 100644
--- a/package.json
+++ b/package.json
@@ -16,8 +16,8 @@
"build-win": "npm run compile-vue && electron-builder --win",
"build-mac": "npm run compile-vue && electron-builder --mac",
"build-docker": "npm run build && sudo docker build -t offs .",
- "publish": "build -p always",
- "docker": "sudo docker run -a STDERR -a STDOUT -p 23402:23402 -p 8200:8200 --name offsystem offs "
+ "publish": "build --win --linux -p always",
+ "docker": "sudo docker run -a STDERR -a STDOUT -p 23402:23402 -p 8200:8200 --name offsystem -v offs:/offs offs"
},
"author": "Prometheus <contact@prometheus.network>",
"license": "GPL-3.0",
@@ -86,6 +86,9 @@
},
"appImage": {
"artifactName": "OFF_System_${version}_linux_${arch}.AppImage"
+ },
+ "deb": {
+ "artifactName": "OFF_System_${version}_linux_${arch}.deb"
}
},
"dependencies": {
@@ -114,9 +117,11 @@
"nat-upnp": "1.1.1",
"network": "0.4.1",
"node-forge": "0.7.6",
+ "pretty-bytes": "^5.1.0",
"protobufjs": "5.0.1",
"protocol-buffers": "3.1.6",
"streamifier": "0.1.1",
+ "streamspeed": "^1.1.1",
"through2": "2.0.3",
"to-array-buffer": "2.1.0",
"urldecode": "1.0.1",
diff --git a/src/block-cache-cluster.js b/src/block-cache-cluster.js
index d21fbe2..7da2cf3 100644
--- a/src/block-cache-cluster.js
+++ b/src/block-cache-cluster.js
@@ -28,7 +28,7 @@ if (cluster.isMaster) {
pool.delete(worker.id)
let cb = _callbacks.get(this)
if (cb) {
- return cb(new Error('Worker Exited Unexpectedly'))
+ cb(new Error('Worker Exited Unexpectedly'))
}
return spawnWorker()
})
@@ -78,35 +78,47 @@ if (cluster.isMaster) {
}
}
content (temps, cb) {
- let worker = this._freeWorker()
- if (worker) {
- _callbacks.set(worker, cb)
- worker.send({type: type.content, temps})
- } else {
- let queue = _queue.get(this)
- queue.unshift({type: type.content, temps, cb: cb})
+ try {
+ let worker = this._freeWorker()
+ if (worker) {
+ _callbacks.set(worker, cb)
+ worker.send({ type: type.content, temps })
+ } else {
+ let queue = _queue.get(this)
+ queue.unshift({ type: type.content, temps, cb: cb })
+ }
+ } catch (err) {
+ return cb(err)
}
}
- contentFilter (temps, cb){
- let worker = this._freeWorker()
- if (worker) {
- _callbacks.set(worker, cb)
- worker.send({type: type.contentFilter, temps})
- } else {
- let queue = _queue.get(this)
- queue.unshift({type: type.contentFilter, temps, cb: cb})
+ contentFilter (temps, cb) {
+ try {
+ let worker = this._freeWorker()
+ if (worker) {
+ _callbacks.set(worker, cb)
+ worker.send({ type: type.contentFilter, temps })
+ } else {
+ let queue = _queue.get(this)
+ queue.unshift({ type: type.contentFilter, temps, cb: cb })
+ }
+ } catch (err) {
+ return cb(err)
}
}
closestBlock (temps, key, filter, cb) {
- let worker = this._freeWorker()
- if (worker) {
- _callbacks.set(worker, cb)
- worker.send({type: type.closestBlock, temps, key, filter})
- } else {
- let queue = _queue.get(this)
- queue.unshift({type: type.closestBlock, temps, key, filter, cb: cb})
+ try {
+ let worker = this._freeWorker()
+ if (worker) {
+ _callbacks.set(worker, cb)
+ worker.send({ type: type.closestBlock, temps, key, filter })
+ } else {
+ let queue = _queue.get(this)
+ queue.unshift({ type: type.closestBlock, temps, key, filter, cb: cb })
+ }
+ } catch (err) {
+ return cb(err)
}
}
_free(threadId) {
@@ -116,9 +128,14 @@ if (cluster.isMaster) {
if (next) {
let pool = _pool.get(this)
let worker = pool.get(threadId)
- _callbacks.set(worker, next.cb)
+ let cb = next.cb
+ _callbacks.set(worker, cb)
delete next.cb
- worker.send({...next})
+ try {
+ worker.send({ ...next })
+ } catch (err) {
+ return cb(err)
+ }
}
})
}
diff --git a/src/block-router.js b/src/block-router.js
index c133c1d..542ef1c 100644
--- a/src/block-router.js
+++ b/src/block-router.js
@@ -51,6 +51,7 @@ module.exports = class BlockRouter extends EventEmitter {
_scheduler.set(this, scheduler)
scheduler.on('error', (err) => this.emit('error', err))
+ scheduler.on('locator', () => this.emit('locator'))
rpc.on('error', (err) => this.emit('error', err))
bc.on('block', (block)=> {
rpc.store(block.hash, config.block, block.data, () => {})
@@ -310,47 +311,51 @@ module.exports = class BlockRouter extends EventEmitter {
}
bootstrap (cb) {
- let bootstrap = config.bootstrap.map((peer) => Peer.fromLocator(peer)).filter((peer) => !peer.isEqual(Peer.self))
- let connect = () => {
- let i = -1
- let next = (err) => {
- if (err) {
- this.emit('error', err)
- }
- i++
- if (i < bootstrap.length) {
- let peer = bootstrap[ i ]
- this.connect(peer, next)
- } else { //Fill routing table with the closet nodes to themselves
- let rpc = _rpc.get(this)
- rpc.findNode(Peer.self.id, cb)
+ try {
+ let bootstrap = config.bootstrap.map((peer) => Peer.fromLocator(peer)).filter((peer) => !peer.isEqual(Peer.self))
+ let connect = () => {
+ let i = -1
+ let next = (err) => {
+ if (err) {
+ this.emit('error', err)
+ }
+ i++
+ if (i < bootstrap.length) {
+ let peer = bootstrap[ i ]
+ this.connect(peer, next)
+ } else { //Fill routing table with the closet nodes to themselves
+ let rpc = _rpc.get(this)
+ rpc.findNode(Peer.self.id, cb)
+ }
}
+ next()
}
- next()
- }
- // If this option is selected then Bootstrap to whomever we were last online with
- if (config.lastKnownPeers) {
- let path = _path.get(this)
- let fd = pth.join(path, '.bucket')
- fs.readFile(fd, (err, bucketFile) => {
- if (err) {
- this.emit(err)
- return connect()
- }
- if (bucketFile) {
- let peers = cbor.decode(toAb(bucketFile))
- for (let pier of peers) {
- let peer = Peer.fromLocator(pier)
- let found = bootstrap.find((boot) => peer.isEqual(boot))
- if (!found) {
- bootstrap.push(peer)
+ // If this option is selected then Bootstrap to whomever we were last online with
+ if (config.lastKnownPeers) {
+ let path = _path.get(this)
+ let fd = pth.join(path, '.bucket')
+ fs.readFile(fd, (err, bucketFile) => {
+ if (err) {
+ this.emit(err)
+ return connect()
+ }
+ if (bucketFile) {
+ let peers = cbor.decode(toAb(bucketFile))
+ for (let pier of peers) {
+ let peer = Peer.fromLocator(pier)
+ let found = bootstrap.find((boot) => peer.isEqual(boot))
+ if (!found) {
+ bootstrap.push(peer)
+ }
}
}
- }
+ return connect()
+ })
+ } else {
return connect()
- })
- } else {
- return connect()
+ }
+ } catch(err) {
+ return cb(err)
}
}
diff --git a/src/command.js b/src/command.js
index 85fe3b5..1607053 100644
--- a/src/command.js
+++ b/src/command.js
@@ -8,6 +8,8 @@ module.exports = new (class Command {
cmd.name('offs')
cmd.version(pkg.version, '-v, --version')
cmd.option('-t, --terminal', 'Run in Terminal Only (without GUI)')
+ cmd.option('-p, --path [dir]', 'Initial path for the application')
+
}
parse() {
cmd.parse(process.argv)
diff --git a/src/config.js b/src/config.js
index 6f2cf45..67c78a0 100644
--- a/src/config.js
+++ b/src/config.js
@@ -46,7 +46,7 @@ let defaults = {
bucketTimeout: 60 * 1000 * 5,
socketTimeout: 120 * 1000,
bootstrap: [
- '5LTX64UZmqxAckP99fRNKutPQCJabbB1xMa1vuCG1Z58SJdLkGa9NkngQNSihHhBPA25evTSSMzqrPJovRLkEykSf7orstw7TCUh1DABKyn3iozxBsL3yKBq7EWz9pHdAE9Fd'
+ 'L8t3oLLfnGZPgkkiAW2FwzHqeWt4pS9amGZQNpPKQgkNrF3JTGxptXuQwc8W7AdaRB34k2afQszr3LQqfUP6hzXgPGu5Rnw28sDwcA3GRrsnqbGYdpLETkSVBNXK1cJwRFRqfD'
]
}
let _blockPath = new WeakMap()
@@ -190,7 +190,7 @@ class Config {
_internalIP.set(this, defaults.internalIP)
_bootstrap.set(this, defaults.bootstrap.slice(0))
_bucketTimeout.set(this, defaults.bucketTimeout)
- _bucketTimeout.set(this, defaults.socketTimeout)
+ _socketTimeout.set(this, defaults.socketTimeout)
}
get blockPath () {
@@ -225,7 +225,7 @@ class Config {
if (!Number.isInteger(+value)) {
throw new TypeError("Invalid Block Cache Size")
}
- if (value < 300) {
+ if (value < 300 * mb) {
throw new TypeError("Block Cache Size Is Too Small")
}
if (value > (549755813 * mb)) {
@@ -243,7 +243,7 @@ class Config {
if (!Number.isInteger(+value)) {
throw new TypeError("Invalid Mini Block Cache Size")
}
- if (value < 300) {
+ if (value < 300 * mb) {
throw new TypeError("Mini Block Cache Size Is Too Small")
}
if (value > (42949672 * mb)) {
@@ -261,7 +261,7 @@ class Config {
if (!Number.isInteger(+value)) {
throw new TypeError("Invalid Nano Block Cache Size")
}
- if (value < 300) {
+ if (value < 300 * mb) {
throw new TypeError("Nano Block Cache Size Is Too Small")
}
if (value > (584115 * mb)) {
@@ -440,7 +440,6 @@ class Config {
}
get socketTimeout () {
return _socketTimeout.get(this)
- this.save()
}
set socketTimeout (value) {
_socketTimeout.set(this, +value)
diff --git a/src/electron/views/export/export.vue b/src/electron/views/export/export.vue
index 7351d17..69bbd79 100644
--- a/src/electron/views/export/export.vue
+++ b/src/electron/views/export/export.vue
@@ -18,6 +18,9 @@
<progressbar :error="file.error" :percent="file.percent"></progressbar>
</td>
</tr>
+ <tr>
+ <strong>Rate:</strong>&nbsp;{{file.rate}}/s
+ </tr>
</table>
</div>
</div>
@@ -162,7 +165,7 @@
}
},
mounted () {
- this.Exporter = new Exporter(ipcRenderer, this.onPercent, this.onError)
+ this.Exporter = new Exporter(ipcRenderer, this.onPercent, this.onSpeed, this.onError)
let heightOffset = window.outerHeight - window.innerHeight
let widthOffset = window.outerWidth - window.innerWidth
let height = this.$refs.container.clientHeight + heightOffset
@@ -178,9 +181,12 @@
})
},
onError (err) {
- this.files[err.id].error = err.err
+ this.files[err.id].error = 'An error occurred'
this.files[err.id].icon = '../../images/error.svg'
},
+ onSpeed (speed) {
+ this.files[speed.id].rate = prettyBytes(speed.rate)
+ },
onPercent(payload) {
this.files[payload.id].percent = payload.percent
if (payload.percent >= 100) {
@@ -207,35 +213,28 @@
}
},
exporter () {
- this.$validator.validateAll()
- .then((ok) => {
- if (!ok) return
- let url = OffUrl.parse(this.url)
- let filename = path.join(this.location, urldecode(url.fileName))
- let streamLength = url.streamLength
- let percent = 0
- let size = 0
- let icon = `../../images/Preloader_${ getRandomInt(1, 7) }.gif`
- let show = true
- let error = null
- let file = {filename, percent, size, streamLength, icon, show, error}
+ this.$validator.validateAll()
+ .then((ok) => {
+ if (!ok) return
+ let url = OffUrl.parse(this.url)
+ let filename = path.join(this.location, urldecode(url.fileName))
+ let streamLength = url.streamLength
+ let percent = 0
+ let size = 0
+ let icon = `../../images/Preloader_${ getRandomInt(1, 7) }.gif`
+ let show = true
+ let error = null
+ let file = {filename, percent, size, streamLength, icon, show, error}
- // Resize Window to fit
- setTimeout(this.resize, 100)
- let id = this.files.length
- this.files.push(file)
- this.Exporter.exporter(this.location, this.url, id)
- //this.location = null
- //this.url = null
- this.$validator.flag('location', {
- valid: false,
- dirty: false
- })
- this.$validator.flag('url', {
- valid: false,
- dirty: false
+ // Resize Window to fit
+ setTimeout(this.resize, 100)
+ let id = this.files.length
+ this.files.push(file)
+ this.Exporter.exporter(this.location, this.url, id)
+ this.location = null
+ this.url = null
+ process.nextTick(() => this.$validator.reset())
})
- })
},
openLocation (index) {
if (this.files[index].percent >= 100) {
diff --git a/src/electron/views/export/index.html b/src/electron/views/export/index.html
index 59ad6ac..0e2082c 100644
--- a/src/electron/views/export/index.html
+++ b/src/electron/views/export/index.html
@@ -23,6 +23,7 @@
const mkdirp = require('mkdirp')
const ipcRenderer = require('electron').ipcRenderer
const Exporter = require('../../../exporter').rendererExporter
+ const prettyBytes = require('pretty-bytes')
</script>
<script src="../../scripts/progress.js"></script>
<script src="index.js"></script>
diff --git a/src/electron/views/export/index.js b/src/electron/views/export/index.js
index 0aba6d6..8e66cb2 100644
--- a/src/electron/views/export/index.js
+++ b/src/electron/views/export/index.js
@@ -13682,6 +13682,7 @@ exports.insert = function (css) {
}
},{}],8:[function(require,module,exports){
+(function (process){
var __vueify_style_dispose__ = require("vueify/lib/insert-css").insert("strong {\n font-family: Odin;\n}\n.button {\n font-family: Odin;\n}\n.file-status {\n border-bottom: 2px solid #ced3cc;\n}\n.icontainer {\n display: flex;\n min-height: 100px;\n min-width: 100px;\n height: 100px;\n width: 100px;\n background-color: #3273dc;\n border-radius: 10px;\n margin: 5px;\n}\n.loader-icon.error {\n background-color: transparent;\n}\n.loader-icon {\n background-color: white;\n border-radius: 10px;\n height: 80px;\n width: 80px;\n margin: 50% 50%;\n transform: translate(-50%, -50%);\n}\n.form-container {\n max-height: 128px;\n max-width: 500px;\n min-height: 128px;\n min-width: 500px;\n height: 128px;\n width: 500px;\n}\n.file-info {\n display: flex;\n}\n.file-status {\n display: flex;\n flex-direction: row;\n margin: 5px;\n}\n\n.download-button {\n height: 100%;\n width: auto;\n min-width: 100px;\n font-family: Odin;\n background-color: #edf0f2;\n padding: 0;\n display: flex;\n border-color: #878787;\n border-style: dotted;\n border-width: 10px;\n padding: 3px;\n color: #878787;\n outline: 5px solid #edf0f2;\n margin: 5px;\n font-family: Odin;\n align-self: center;\n align-content: center;\n justify-content: center;\n flex-direction: column;\n}\n.download {\n width: 40px;\n height: 40px;\n margin: 0 auto 3px auto;\n}\n.download-button:hover h3 {\n color: #878787;\n}\n.download-button:hover {\n outline: 5px solid #878787;\n}\n.error {\n color: red;\n}")
;(function(){
//
@@ -13830,6 +13831,9 @@ var __vueify_style_dispose__ = require("vueify/lib/insert-css").insert("strong {
//
//
//
+//
+//
+//
let progressbar = require('./progressbar.vue')
let urldecode = require('urldecode')
@@ -13848,7 +13852,7 @@ module.exports = {
}
},
mounted () {
- this.Exporter = new Exporter(ipcRenderer, this.onPercent, this.onError)
+ this.Exporter = new Exporter(ipcRenderer, this.onPercent, this.onSpeed, this.onError)
let heightOffset = window.outerHeight - window.innerHeight
let widthOffset = window.outerWidth - window.innerWidth
let height = this.$refs.container.clientHeight + heightOffset
@@ -13864,9 +13868,12 @@ module.exports = {
})
},
onError (err) {
- this.files[err.id].error = err.err
+ this.files[err.id].error = 'An error occurred'
this.files[err.id].icon = '../../images/error.svg'
},
+ onSpeed (speed) {
+ this.files[speed.id].rate = prettyBytes(speed.rate)
+ },
onPercent(payload) {
this.files[payload.id].percent = payload.percent
if (payload.percent >= 100) {
@@ -13893,35 +13900,28 @@ module.exports = {
}
},
exporter () {
- this.$validator.validateAll()
- .then((ok) => {
- if (!ok) return
- let url = OffUrl.parse(this.url)
- let filename = path.join(this.location, urldecode(url.fileName))
- let streamLength = url.streamLength
- let percent = 0
- let size = 0
- let icon = `../../images/Preloader_${ getRandomInt(1, 7) }.gif`
- let show = true
- let error = null
- let file = {filename, percent, size, streamLength, icon, show, error}
-
- // Resize Window to fit
- setTimeout(this.resize, 100)
- let id = this.files.length
- this.files.push(file)
- this.Exporter.exporter(this.location, this.url, id)
- //this.location = null
- //this.url = null
- this.$validator.flag('location', {
- valid: false,
- dirty: false
- })
- this.$validator.flag('url', {
- valid: false,
- dirty: false
+ this.$validator.validateAll()
+ .then((ok) => {
+ if (!ok) return
+ let url = OffUrl.parse(this.url)
+ let filename = path.join(this.location, urldecode(url.fileName))
+ let streamLength = url.streamLength
+ let percent = 0
+ let size = 0
+ let icon = `../../images/Preloader_${ getRandomInt(1, 7) }.gif`
+ let show = true
+ let error = null
+ let file = {filename, percent, size, streamLength, icon, show, error}
+
+ // Resize Window to fit
+ setTimeout(this.resize, 100)
+ let id = this.files.length
+ this.files.push(file)
+ this.Exporter.exporter(this.location, this.url, id)
+ this.location = null
+ this.url = null
+ process.nextTick(() => this.$validator.reset())
})
- })
},
openLocation (index) {
if (this.files[index].percent >= 100) {
@@ -13939,7 +13939,7 @@ module.exports = {
if (module.exports.__esModule) module.exports = module.exports.default
var __vue__options__ = (typeof module.exports === "function"? module.exports.options: module.exports)
if (__vue__options__.functional) {console.error("[vueify] functional components are not supported and should be defined in plain js files using render functions.")}
-__vue__options__.render = function render () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{ref:"container"},[_c('div',{ref:"fileStatus"},_vm._l((_vm.files),function(file,index){return _c('div',{directives:[{name:"show",rawName:"v-show",value:(file.show),expression:"file.show"}],staticClass:"file-status"},[_c('div',{staticClass:"icontainer"},[_c('img',{class:file.error ? 'loader-icon error' : 'loader-icon',attrs:{"src":file.icon},on:{"click":function($event){_vm.openLocation(index)}}})]),_vm._v(" "),_c('div',{staticClass:"file-info"},[_c('table',[_c('tr',[_c('td',[_c('strong',[_vm._v("Filename:")]),_vm._v("\n "+_vm._s(file.filename)+"\n ")])]),_vm._v(" "),_c('tr',[_c('td',[_c('progressbar',{attrs:{"error":file.error,"percent":file.percent}})],1)])])])])})),_vm._v(" "),_c('div',{staticClass:"form-container"},[_c('form',[_c('table',[_c('tr',[_c('td',{staticStyle:{"padding":"5px"}},[_c('div',{staticClass:"field has-addons"},[_c('div',{staticClass:"control"},[_c('input',{directives:[{name:"model",rawName:"v-model",value:(_vm.location),expression:"location"}],staticClass:"input",attrs:{"disabled":"","name":"location","type":"text","placeholder":"Select an Export Location"},domProps:{"value":(_vm.location)},on:{"input":function($event){if($event.target.composing){ return; }_vm.location=$event.target.value}}})]),_vm._v(" "),_c('div',{staticClass:"control"},[_c('a',{staticClass:"button is-info",on:{"click":_vm.choose}},[_vm._v("\n Choose\n ")])])]),_vm._v(" "),_c('input',{directives:[{name:"show",rawName:"v-show",value:(false),expression:"false"},{name:"validate",rawName:"v-validate",value:({ required: true }),expression:"{ required: true }"},{name:"model",rawName:"v-model",value:(_vm.location),expression:"location"}],staticClass:"input",attrs:{"name":"location","type":"text","placeholder":"Select an Export Location"},domProps:{"value":(_vm.location)},on:{"input":function($event){if($event.target.composing){ return; }_vm.location=$event.target.value}}}),_vm._v(" "),_c('span',{directives:[{name:"show",rawName:"v-show",value:(_vm.errors.has('location')),expression:"errors.has('location')"}],staticClass:"error"},[_vm._v(_vm._s(_vm.errors.first('location')))]),_vm._v(" "),_c('div',{staticClass:"field has-addons"},[_c('div',{staticClass:"control"},[_c('input',{directives:[{name:"validate",rawName:"v-validate",value:({ required: true, regex: /\/offsystem\/v3\/([-+.\w]+\/[-+.\w]+)\/(\d+)\/([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)\/([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)\/([^ !$`&*()+]*|\\[ !$`&*()+]*)+/ }),expression:"{ required: true, regex: /\\/offsystem\\/v3\\/([-+.\\w]+\\/[-+.\\w]+)\\/(\\d+)\\/([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)\\/([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)\\/([^ !$`&*()+]*|\\\\[ !$`&*()+]*)+/ }"},{name:"model",rawName:"v-model",value:(_vm.url),expression:"url"}],staticClass:"input",staticStyle:{"width":"340px"},attrs:{"name":"url","type":"text","placeholder":"Enter url to export"},domProps:{"value":(_vm.url)},on:{"input":function($event){if($event.target.composing){ return; }_vm.url=$event.target.value}}})])]),_vm._v(" "),_c('span',{directives:[{name:"show",rawName:"v-show",value:(_vm.errors.has('url') && _vm.fields.url.dirty),expression:"errors.has('url') && fields.url.dirty"}],staticClass:"error"},[_vm._v(_vm._s(_vm.errors.first('url')))])]),_vm._v(" "),_c('td',[_c('a',{staticClass:"download-button",on:{"click":_vm.exporter}},[_c('h3',{attrs:{"id":"downloadMessage"}},[_vm._v("Export")]),_vm._v(" "),_c('img',{staticClass:"download",attrs:{"id":"downloadIcon","src":"../../images/download.svg"}})])])])])])])])}
+__vue__options__.render = function render () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{ref:"container"},[_c('div',{ref:"fileStatus"},_vm._l((_vm.files),function(file,index){return _c('div',{directives:[{name:"show",rawName:"v-show",value:(file.show),expression:"file.show"}],staticClass:"file-status"},[_c('div',{staticClass:"icontainer"},[_c('img',{class:file.error ? 'loader-icon error' : 'loader-icon',attrs:{"src":file.icon},on:{"click":function($event){_vm.openLocation(index)}}})]),_vm._v(" "),_c('div',{staticClass:"file-info"},[_c('table',[_c('tr',[_c('td',[_c('strong',[_vm._v("Filename:")]),_vm._v("\n "+_vm._s(file.filename)+"\n ")])]),_vm._v(" "),_c('tr',[_c('td',[_c('progressbar',{attrs:{"error":file.error,"percent":file.percent}})],1)]),_vm._v(" "),_c('tr',[_c('strong',[_vm._v("Rate:")]),_vm._v(" "+_vm._s(file.rate)+"/s\n ")])])])])})),_vm._v(" "),_c('div',{staticClass:"form-container"},[_c('form',[_c('table',[_c('tr',[_c('td',{staticStyle:{"padding":"5px"}},[_c('div',{staticClass:"field has-addons"},[_c('div',{staticClass:"control"},[_c('input',{directives:[{name:"model",rawName:"v-model",value:(_vm.location),expression:"location"}],staticClass:"input",attrs:{"disabled":"","name":"location","type":"text","placeholder":"Select an Export Location"},domProps:{"value":(_vm.location)},on:{"input":function($event){if($event.target.composing){ return; }_vm.location=$event.target.value}}})]),_vm._v(" "),_c('div',{staticClass:"control"},[_c('a',{staticClass:"button is-info",on:{"click":_vm.choose}},[_vm._v("\n Choose\n ")])])]),_vm._v(" "),_c('input',{directives:[{name:"show",rawName:"v-show",value:(false),expression:"false"},{name:"validate",rawName:"v-validate",value:({ required: true }),expression:"{ required: true }"},{name:"model",rawName:"v-model",value:(_vm.location),expression:"location"}],staticClass:"input",attrs:{"name":"location","type":"text","placeholder":"Select an Export Location"},domProps:{"value":(_vm.location)},on:{"input":function($event){if($event.target.composing){ return; }_vm.location=$event.target.value}}}),_vm._v(" "),_c('span',{directives:[{name:"show",rawName:"v-show",value:(_vm.errors.has('location')),expression:"errors.has('location')"}],staticClass:"error"},[_vm._v(_vm._s(_vm.errors.first('location')))]),_vm._v(" "),_c('div',{staticClass:"field has-addons"},[_c('div',{staticClass:"control"},[_c('input',{directives:[{name:"validate",rawName:"v-validate",value:({ required: true, regex: /\/offsystem\/v3\/([-+.\w]+\/[-+.\w]+)\/(\d+)\/([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)\/([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)\/([^ !$`&*()+]*|\\[ !$`&*()+]*)+/ }),expression:"{ required: true, regex: /\\/offsystem\\/v3\\/([-+.\\w]+\\/[-+.\\w]+)\\/(\\d+)\\/([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)\\/([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+)\\/([^ !$`&*()+]*|\\\\[ !$`&*()+]*)+/ }"},{name:"model",rawName:"v-model",value:(_vm.url),expression:"url"}],staticClass:"input",staticStyle:{"width":"340px"},attrs:{"name":"url","type":"text","placeholder":"Enter url to export"},domProps:{"value":(_vm.url)},on:{"input":function($event){if($event.target.composing){ return; }_vm.url=$event.target.value}}})])]),_vm._v(" "),_c('span',{directives:[{name:"show",rawName:"v-show",value:(_vm.errors.has('url') && _vm.fields.url.dirty),expression:"errors.has('url') && fields.url.dirty"}],staticClass:"error"},[_vm._v(_vm._s(_vm.errors.first('url')))])]),_vm._v(" "),_c('td',[_c('a',{staticClass:"download-button",on:{"click":_vm.exporter}},[_c('h3',{attrs:{"id":"downloadMessage"}},[_vm._v("Export")]),_vm._v(" "),_c('img',{staticClass:"download",attrs:{"id":"downloadIcon","src":"../../images/download.svg"}})])])])])])])])}
__vue__options__.staticRenderFns = []
if (module.hot) {(function () { var hotAPI = require("vue-hot-reload-api")
hotAPI.install(require("vue"), true)
@@ -13952,7 +13952,8 @@ if (module.hot) {(function () { var hotAPI = require("vue-hot-reload-api")
hotAPI.reload("data-v-6a61d36e", __vue__options__)
}
})()}
-},{"./progressbar.vue":10,"urldecode":3,"vue":6,"vue-hot-reload-api":5,"vueify/lib/insert-css":7}],9:[function(require,module,exports){
+}).call(this,require('_process'))
+},{"./progressbar.vue":10,"_process":1,"urldecode":3,"vue":6,"vue-hot-reload-api":5,"vueify/lib/insert-css":7}],9:[function(require,module,exports){
var Vue = require('vue')
var App = require('./export.vue')
var VeeValidate = require('vee-validate')
diff --git a/src/electron/views/update/update.vue b/src/electron/views/update/update.vue
index e24295a..486718a 100644
--- a/src/electron/views/update/update.vue
+++ b/src/electron/views/update/update.vue
@@ -78,7 +78,7 @@
mounted () {
let onError = (err) => {
this.error = err
- this.status = err
+ this.status = 'An error occurred'
}
let onCheckingForUpdate = () => {
this.status = 'Checking for update'
diff --git a/src/exporter.js b/src/exporter.js
index 9ad28fc..6d52b87 100644
--- a/src/exporter.js
+++ b/src/exporter.js
@@ -1,14 +1,15 @@
-let OffUrl= require('./off-url')
-let path = require('path')
-let mkdirp = require('mkdirp')
-let http = require('http')
-let collect = require('collect-stream')
-let fs = require('fs')
-let responder = require('electron-ipc-responder')
-let util = require('./utility')
+const OffUrl= require('./off-url')
+const path = require('path')
+const mkdirp = require('mkdirp')
+const http = require('http')
+const collect = require('collect-stream')
+const fs = require('fs')
+const responder = require('electron-ipc-responder')
+const util = require('./utility')
+const Speed = require('streamspeed')
class rendererExporter extends responder {
- constructor (ipcRenderer, onPercent, onError) {
+ constructor (ipcRenderer, onPercent, onSpeed, onError) {
super(ipcRenderer.send.bind(ipcRenderer), ipcRenderer.on.bind(ipcRenderer))
this.registerTopic('percent', async (payload) => {
onPercent(payload)
@@ -16,6 +17,9 @@ class rendererExporter extends responder {
this.registerTopic('error',async (payload) => {
onError(payload)
})
+ this.registerTopic('speed',async (payload) => {
+ onSpeed(payload)
+ })
}
async exporter (location, url, id) {
await this.ask('export', {location, url, id})
@@ -39,6 +43,11 @@ class mainExporter extends responder {
if (url.contentType === 'offsystem/directory') {
file.filename = file.filename.replace('.ofd', '')
let cb = (response) => {
+ let speed = new Speed()
+ speed.on('speed', (rate) => {
+ this.tell('speed', {id: payload.id, rate})
+ })
+ speed.add(response)
collect(response, async (err, data) => {
if (err) {
return this.tell('error', {id: payload.id, err})
@@ -67,6 +76,11 @@ class mainExporter extends responder {
mkdirp.sync(path.join(payload.location, dir, fp.dir))
}
let ws = fs.createWriteStream(path.join(payload.location, dir, key))
+ let speed = new Speed()
+ speed.on('speed', (rate) => {
+ this.tell('speed', {id: payload.id, rate})
+ })
+ speed.add(response)
response.on('data', async (chunk) => {
file.size += chunk.length
file.percent = Math.floor((file.size/file.streamLength) * 100)
@@ -94,6 +108,12 @@ class mainExporter extends responder {
} else {
let cb = (response) => {
let ws = fs.createWriteStream(filename)
+ let speed = new Speed()
+ speed.on('speed', (rate) => {
+ this.tell('speed', {id: payload.id, rate})
+ })
+ speed.add(response)
+
ws.on('error', (err) => {
this.tell('error', {id: payload.id, err})
})
diff --git a/src/index.js b/src/index.js
index c8ba77f..146c41b 100644
--- a/src/index.js
+++ b/src/index.js
@@ -27,17 +27,23 @@ const log = require('js-logging')
}
})
-let win
+
let node
-if (process.env.ELECTRON_RUN_AS_NODE || cmd.terminal) {
- node = new Node('OFFSYSTEM')
+function createNode() {
+ node = new Node('OFFSYSTEM', cmd.path)
node.on('error', log.error)
node.on('bootstrapped', (connections) => log.notice(`Boostrapped with ${connections} connections`))
node.on('ready', () => {
log.notice(`Node ${node.peerInfo.key} is online externally at ${node.peerInfo.extIp} and port ${node.peerInfo.extPort}`)
log.notice(`Node ${node.peerInfo.key} is online internally at ${node.peerInfo.intIp} and port ${node.peerInfo.intPort}`)
+ log.notice(`Locator ${node.peerInfo.toLocator()}`)
})
+ node.on('locator', () => log.notice(`Locator ${node.peerInfo.toLocator()}`))
node.on('listening', (port) => log.notice(`HTTP Server is online at ${node.peerInfo.ip} and port ${port}`))
+ node.start()
+}
+if (process.env.ELECTRON_RUN_AS_NODE || cmd.terminal) {
+ createNode()
} else {
const { app, Menu, MenuItem, Tray, BrowserWindow, clipboard, ipcMain } = require('electron')
const {autoUpdater} = require("electron-updater")
@@ -49,18 +55,7 @@ if (process.env.ELECTRON_RUN_AS_NODE || cmd.terminal) {
app.quit()
}
function createTray () {
- /*if (process.env.NODE_ENV === 'development') {
- devTools.install()
- }*/
- node = new Node('OFFSYSTEM')
- node.on('error', log.error)
- node.on('bootstrapped', (connections) => log.notice(`Boostrapped with ${connections} connections`))
- node.on('ready', () => {
- log.notice(`Node ${node.peerInfo.key} is online externally at ${node.peerInfo.extIp} and port ${node.peerInfo.extPort}`)
- log.notice(`Node ${node.peerInfo.key} is online internally at ${node.peerInfo.intIp} and port ${node.peerInfo.intPort}`)
- })
- node.on('listening', (port) => log.notice(`HTTP Server is online at ${node.peerInfo.ip} and port ${port}`))
- node.start()
+ createNode()
node.once('ready', () => {
let importWin
@@ -306,7 +301,19 @@ if (process.env.ELECTRON_RUN_AS_NODE || cmd.terminal) {
})
}
function createUpdateWindow () {
- let updateWin = new BrowserWindow({ width: 300, height: 150, icon: icon, autoHideMenuBar: true, resizable: false , show: false})
+ let width
+ let height
+ if (/^win/.test(process.platform)) {
+ width = 300
+ height = 200
+ } else if (/^darwin/.test(process.platform)) {
+ width = 300
+ height = 200
+ } else {
+ width = 300
+ height = 150
+ }
+ let updateWin = new BrowserWindow({ width, height, icon: icon, autoHideMenuBar: true, resizable: false , show: false})
let onComplete = () => {
updateWin.close()
createTray()
@@ -321,18 +328,10 @@ if (process.env.ELECTRON_RUN_AS_NODE || cmd.terminal) {
}
app.on('ready', () =>{
- if (autoUpdater.isPackaged) {
- createUpdateWindow()
- } else {
+ if (process.defaultApp) {
createTray()
- }
- })
-
- app.on('activate', () => {
- // On macOS it's common to re-create a window in the app when the
- // dock icon is clicked and there are no other windows open.
- if (win === null) {
- createWindow()
+ } else {
+ createUpdateWindow()
}
})
}
diff --git a/src/node.js b/src/node.js
index dab5c5c..528e5e5 100644
--- a/src/node.js
+++ b/src/node.js
@@ -64,7 +64,7 @@ module.exports = class Node extends EventEmitter {
let getPeer = (err, intIP)=> {
if (err) {
this.emit('error', err)
- ip = '127.0.0.1'
+ intIP = '127.0.0.1'
}
let pk = keyPair.publicKey
let id = util.hash(pk)
@@ -74,6 +74,7 @@ module.exports = class Node extends EventEmitter {
let blockRouter = new BlockRouter(config.cacheLocation, appFolder)
_blockRouter.set(this, blockRouter)
blockRouter.on('error', (err) => this.emit('error', err))
+ blockRouter.on('locator', () => this.emit('locator'))
let server = Server(blockRouter, this.emit.bind(this))
_server.set(this, server)
server.listen(config.httpPort, () => {
diff --git a/src/scheduler.js b/src/scheduler.js
index aca7c92..1fb68c9 100644
--- a/src/scheduler.js
+++ b/src/scheduler.js
@@ -188,32 +188,11 @@ module.exports = class Scheduler extends EventEmitter {
capacityJob(nano, config.nano)
bucket.on('ping', onPing)
- let maintainBucket = ()=> {
- let nodes = bucket.toArray()
- let i = -1
- let next = (err)=> {
- if (err) {
- bucket.remove(nodes[ i ])
- }
- i++
- if (i < nodes.length) {
- let node = nodes[ i ]
- rpc.ping(node.id, next)
- } else {
- rebootstrap(() => {
- let maintenanceJob = setTimeout(maintainBucket, config.bucketTimeout)
- _maintenanceJob.set(this, maintenanceJob)
- })
- }
- }
- checkIP(next)
- }
- let maintenanceJob = setTimeout(maintainBucket, config.bucketTimeout)
- _maintenanceJob.set(this, maintenanceJob)
let rebootstrap = (cb) => {
try {
+ let peers = bucket.toArray()
let bootstrap = config.bootstrap.map((peer) => Peer.fromLocator(peer))
- .filter((peer) => !peer.isEqual(Peer.self) && !bucket.contains(peer.id))
+ .filter((peer) => !peer.isEqual(Peer.self) && !peers.find((pier) => pier.isEqual(peer)))
let i = -1
let next = (err) => {
@@ -235,6 +214,29 @@ module.exports = class Scheduler extends EventEmitter {
return cb()
}
}
+ let maintainBucket = () => {
+ let nodes = bucket.toArray()
+ let i = -1
+ let next = (err)=> {
+ if (err) {
+ bucket.remove(nodes[ i ])
+ }
+ i++
+ if (i < nodes.length) {
+ let node = nodes[ i ]
+ rpc.ping(node.id, next)
+ } else {
+ rebootstrap(() => {
+ let maintenanceJob = setTimeout(maintainBucket, config.bucketTimeout)
+ _maintenanceJob.set(this, maintenanceJob)
+ })
+ }
+ }
+ checkIP(next)
+ }
+ let maintenanceJob = setTimeout(maintainBucket, config.bucketTimeout)
+ _maintenanceJob.set(this, maintenanceJob)
+
let checkIP = (cb) => {
let intIP
let extIP
@@ -250,12 +252,12 @@ module.exports = class Scheduler extends EventEmitter {
}
if (Peer.self.intIp !== intIp || Peer.self.extIp !== extIp) {
Peer.self = new Peer(Peer.self.id, extIp, Peer.self.extPort, intIp, Peer.self.intPort)
+ this.emit('locator')
}
return cb()
})
})
}
-
}
}