diff --git a/src/app/admin-page.js b/src/app/admin-page.js
index 7ea44cb..9ae2518 100644
--- a/src/app/admin-page.js
+++ b/src/app/admin-page.js
@@ -134,24 +134,6 @@ export default class AdminPage extends Page {
}} />
-
-
CPU usage limitation
-
{
- if(value === 100)
- value = 0
-
- this.options.spider.cpuLimit = value
- this.forceUpdate()
- }}
- />
-
-
Download torrents directory
+ Torrent network scanner settings:
+
+
+
Scanner walk speed (current: {this.options.spider && this.options.spider.walkInterval}) [affected after program reload]
+
{
+ this.options.spider.walkInterval = value
+ this.forceUpdate()
+ }}
+ />
+
+
* Low value - fast initial scanning and high cpu usage. High Value - low cpu usage but very slow scanning.
+ Good value between 3-60. Defaul value: 5
+
+
+
+
Nodes usage (current: {this.options.spider && this.options.spider.nodesUsage})
+
{
+ this.options.spider.nodesUsage = value
+ this.forceUpdate()
+ }}
+ />
+
+
* Low Value - very low usage of nodes, low network traffic, slow torrent scanning. High value - high traffic, fast scanning, high routers usage.
+ Recomended value between 10-1000. Defaul value: 100. 0 - Ignore this option (no limit).
+
+
+
+
+
Reduce network packages (current: {this.options.spider && this.options.spider.packagesLimit})
+
{
+ this.options.spider.packagesLimit = value
+ this.forceUpdate()
+ }}
+ />
+
+
* Low Value - ignore more usless network packages, lower traffic and routers usage. High Value - high traffic and router usage in prospectю
+ Recomended value between 300-2000. Defaul value: 500. 0 - Ignore this option (no limit).
+
+
+
{
this.settingsSavedMessage
&&
diff --git a/src/background/bt/spider.js b/src/background/bt/spider.js
index aa4a436..8558dfc 100644
--- a/src/background/bt/spider.js
+++ b/src/background/bt/spider.js
@@ -5,14 +5,9 @@ const Emiter = require('events')
const bencode = require('bencode')
const {Table, Node} = require('./table')
const Token = require('./token')
-const cpuUsage = require('./cpu-usage')
const config = require('../config')
const fs = require('fs')
-const _debug = require('debug')
-const cpuDebug = _debug('spider:cpu')
-const trafficDebug = _debug('spider:traffic')
-
const bootstraps = [{
address: 'router.bittorrent.com',
port: 6881
@@ -45,11 +40,14 @@ class Spider extends Emiter {
this.client = client
this.ignore = false; // ignore all requests
this.initialized = false;
- this.trafficSpeed = 0
this.walkInterval = config.spider.walkInterval;
- this.cpuLimit = config.spider.cpuLimit;
- this.cpuInterval = config.spider.cpuInterval;
+ this.foundSpeed = 0;
+ this.foundCounter = 0;
+ setInterval(() => {
+ this.foundSpeed = this.foundCounter;
+ this.foundCounter = 0;
+ }, 1000)
this.announceHashes = []
}
@@ -72,7 +70,7 @@ class Spider extends Emiter {
this.send(message, address)
}
- getPeersRequest(infoHash) {
+ getPeersRequest(infoHash, address) {
const message = {
t: generateTid(),
y: 'q',
@@ -82,13 +80,7 @@ class Spider extends Emiter {
info_hash: infoHash
}
}
- for(const address of this.table.nodes)
- {
- if(parseInt(Math.random() * 5) !== 1)
- continue;
-
- this.send(message, address)
- }
+ this.send(message, address)
}
announcePeer(infoHash, token, address, port)
@@ -119,14 +111,10 @@ class Spider extends Emiter {
return
if(!this.client || this.client.isIdle()) {
- if(
- !this.ignore
- && (this.cpuLimit <= 0 || cpuUsage() < this.cpuLimit + this.cpuInterval)
- && (config.trafficMax <= 0 || this.trafficSpeed == 0 || this.trafficSpeed < config.trafficMax)
- )
+ if(!this.ignore)
{
const node = this.table.shift()
- if (node) {
+ if (node && (config.spider.nodesUsage === 0 || parseInt(Math.random() * this.table.nodes.length / config.spider.nodesUsage) === 0)) {
this.findNode(Node.neighbor(node.id, this.table.id), {address: node.address, port: node.port})
}
}
@@ -170,11 +158,8 @@ class Spider extends Emiter {
}
onFindNodeRequest(message, address) {
- if(this.cpuLimit > 0 && cpuUsage() > this.cpuLimit) {
- return
- }
-
- if(config.trafficIgnoreDHT && config.trafficMax > 0 && this.trafficSpeed > 0 && this.trafficSpeed > config.trafficMax) {
+ if(config.spider.packagesLimit !== 0 && this.foundSpeed > config.spider.packagesLimit)
+ {
return
}
@@ -192,14 +177,17 @@ class Spider extends Emiter {
nodes: Node.encodeNodes(this.table.first())
}
}, address)
+
+ // also check hashes of alive ones
+ for(const hash of this.announceHashes)
+ {
+ this.getPeersRequest(hash, address)
+ }
}
onGetPeersRequest(message, address) {
- if(this.cpuLimit > 0 && cpuUsage() > this.cpuLimit) {
- return
- }
-
- if(config.trafficIgnoreDHT && config.trafficMax > 0 && this.trafficSpeed > 0 && this.trafficSpeed > config.trafficMax) {
+ if(config.spider.packagesLimit !== 0 && this.foundSpeed > config.spider.packagesLimit)
+ {
return
}
@@ -220,6 +208,12 @@ class Spider extends Emiter {
}, address)
this.emit('unensureHash', infohash.toString('hex').toUpperCase())
+
+ // also check hashes of alive ones
+ for(const hash of this.announceHashes)
+ {
+ this.getPeersRequest(hash, address)
+ }
}
onAnnouncePeerRequest(message, address) {
@@ -239,19 +233,13 @@ class Spider extends Emiter {
};
this.emit('ensureHash', infohash.toString('hex').toUpperCase(), addressPair)
if(this.client && !this.ignore) {
- cpuDebug('cpu usage:' + cpuUsage())
- if(this.cpuLimit <= 0 || cpuUsage() <= this.cpuLimit + this.cpuInterval) {
- this.client.add(addressPair, infohash);
- }
+ this.client.add(addressPair, infohash);
}
}
onPingRequest(message, address) {
- if(this.cpuLimit > 0 && cpuUsage() > this.cpuLimit) {
- return
- }
-
- if(config.trafficIgnoreDHT && config.trafficMax > 0 && this.trafficSpeed > 0 && this.trafficSpeed > config.trafficMax) {
+ if(config.spider.packagesLimit !== 0 && this.foundSpeed > config.spider.packagesLimit)
+ {
return
}
@@ -263,11 +251,13 @@ class Spider extends Emiter {
const message = bencode.decode(data)
if (message.y.toString() == 'r') {
if(message.r.nodes) {
+ this.foundCounter++;
this.onFoundNodes(message.r.nodes, message.r.token, address)
} else if(message.r.values) {
this.onFoundPeers(message.r.values, message.r.token, address)
}
} else if (message.y.toString() == 'q') {
+ this.foundCounter++;
switch(message.q.toString()) {
case 'get_peers':
this.onGetPeersRequest(message, address)
@@ -308,39 +298,6 @@ class Spider extends Emiter {
}, 3000)
this.join()
this.walk()
-
- if(config.trafficMax > 0)
- {
- trafficDebug('inore dht traffic', config.trafficIgnoreDHT)
- const path = `/sys/class/net/${config.trafficInterface}/statistics/rx_bytes`
- if(fs.existsSync(path))
- {
- trafficDebug('limitation', config.trafficMax / 1024, 'kbps/s')
- let traffic = 0
- this.trafficInterval = setInterval(() => {
- fs.readFile(path, (err, newTraffic) => {
- if(err)
- return
-
- if(traffic === 0)
- traffic = newTraffic
-
- this.trafficSpeed = (newTraffic - traffic) / config.trafficUpdateTime
-
- trafficDebug('traffic rx', this.trafficSpeed / 1024, 'kbps/s')
-
- traffic = newTraffic
- })
- }, 1000 * config.trafficUpdateTime)
- }
- }
-
- this.announceSearchInterval = setInterval(() => {
- for(const hash of this.announceHashes)
- {
- this.getPeersRequest(hash)
- }
- }, 3000)
}
close(callback)
@@ -351,10 +308,6 @@ class Spider extends Emiter {
return
}
clearInterval(this.joinInterval)
- if(this.trafficInterval)
- clearInterval(this.trafficInterval)
- if(this.announceSearchInterval)
- clearInterval(this.announceSearchInterval)
this.closing = true
this.udp.close(() => {
this.initialized = false
diff --git a/src/background/config.js b/src/background/config.js
index 3cbb871..cca922c 100644
--- a/src/background/config.js
+++ b/src/background/config.js
@@ -21,8 +21,8 @@ let config = {
spider: {
walkInterval: 5,
- cpuLimit: 0,
- cpuInterval: 10,
+ nodesUsage: 100,
+ packagesLimit: 500
},
downloader: {
@@ -35,11 +35,6 @@ let config = {
spaceQuota: false,
spaceDiskLimit: 7 * 1024 * 1024 * 1024,
- trafficInterface: 'enp2s0',
- trafficMax: 0,
- trafficUpdateTime: 3, //secs
- trafficIgnoreDHT: false,
-
dbPath: '',
client: {
@@ -81,7 +76,18 @@ config.load = () => {
const obj = JSON.parse(data);
for(let prop in obj)
{
- config[prop] = obj[prop]
+ // объединяем объекты
+ if(typeof config[prop] === 'object' && typeof obj[prop] === 'object')
+ {
+ for(const subProp in obj[prop])
+ {
+ config[prop][subProp] = obj[prop][subProp]
+ }
+ }
+ else
+ {
+ config[prop] = obj[prop]
+ }
debug('rats.json:', prop, '=', obj[prop])
}
}
diff --git a/src/background/p2p.js b/src/background/p2p.js
new file mode 100644
index 0000000..ec22883
--- /dev/null
+++ b/src/background/p2p.js
@@ -0,0 +1,126 @@
+const config = require('./config');
+const net = require('net')
+const JsonSocket = require('json-socket')
+
+class p2p {
+ peers = []
+ ignoreAddresses = []
+ messageHandlers = {}
+ size = 0
+
+ constructor(send = () => {})
+ {
+ this.send = send
+ this.tcpServer = net.createServer();
+ this.tcpServer.on('connection', (socket) => {
+ //console.log('p2p server connection', socket.remoteAddress)
+ socket = new JsonSocket(socket);
+ socket.on('error', (err) => {})
+ socket.on('message', (message) => {
+ if(message.type && this.messageHandlers[message.type])
+ {
+ this.messageHandlers[message.type](message.data, (data) => {
+ socket.sendMessage({
+ id: message.id,
+ data
+ });
+ })
+ }
+ });
+ })
+ }
+
+ listen() {
+ console.log('listen p2p on', config.spiderPort, 'port')
+ this.tcpServer.listen(config.spiderPort);
+ }
+
+ on(type, callback) {
+ this.messageHandlers[type] = callback
+ }
+
+ add(address) {
+ const { peers } = this
+
+ if(this.size > 10)
+ return;
+
+ if(address.port <= 1 || address.port > 65535)
+ return;
+
+ if(this.ignoreAddresses.includes(address.address))
+ return;
+
+ for(let peer of peers)
+ {
+ if(peer.address === address.address) {
+ peer.port = address.port;
+ return;
+ }
+ }
+ this.connect(address)
+ }
+
+ connect(address)
+ {
+ this.peers.push(address)
+ const socket = new JsonSocket(new net.Socket()); //Decorate a standard net.Socket with JsonSocket
+ socket.on('connect', () => { //Don't send until we're connected
+ // add to peers
+ this.size++;
+ this.send('peer', this.size)
+ console.log('new peer', address)
+
+ const callbacks = {}
+ socket.on('message', (message) => {
+ if(message.id && callbacks[message.id])
+ {
+ callbacks[message.id](message.data);
+ delete callbacks[message.id];
+ }
+ });
+
+ const emit = (type, data, callback) => {
+ const id = Math.random().toString(36).substring(5)
+ if(callback)
+ callbacks[id] = callback;
+ socket.sendMessage({
+ id,
+ type,
+ data
+ });
+ }
+ address.emit = emit
+ });
+
+ socket.on('close', () => {
+ const index = this.peers.indexOf(address);
+ if(index >= 0)
+ {
+ if(this.peers[index].emit) // only autorized peers
+ {
+ this.size--;
+ this.send('peer', this.size)
+ }
+ this.peers.splice(index, 1);
+
+ console.log('close peer connection', address)
+ }
+ })
+
+ socket.on('error', (err) => {})
+
+ socket.connect(address.port, address.address);
+ }
+
+ emit(type, data, callback)
+ {
+ for(const peer of this.peers)
+ {
+ if(peer.emit)
+ peer.emit(type, data, callback)
+ }
+ }
+}
+
+module.exports = p2p
\ No newline at end of file
diff --git a/src/background/spider.js b/src/background/spider.js
index a85ba41..2e03840 100644
--- a/src/background/spider.js
+++ b/src/background/spider.js
@@ -3,9 +3,8 @@ const client = new (require('./bt/client'))
const spider = new (require('./bt/spider'))(client)
const mysql = require('mysql');
const getPeersStatisticUDP = require('./bt/udp-tracker-request')
-const net = require('net')
-const JsonSocket = require('json-socket')
const crypto = require('crypto')
+const P2PServer = require('./p2p')
const stun = require('stun')
//var express = require('express');
//var app = express();
@@ -253,30 +252,8 @@ setInterval(() => {
topCache = {};
}, 24 * 60 * 60 * 1000);
-
-
-// socket
-const messageHandlers = {}
-const onSocketMessage = (type, callback) => {
- messageHandlers[type] = callback
-}
-const tcpServer = net.createServer();
-tcpServer.listen(config.spiderPort);
-tcpServer.on('connection', (socket) => {
- socket = new JsonSocket(socket);
- socket.on('error', (err) => {})
- socket.on('message', (message) => {
- if(message.type && messageHandlers[message.type])
- {
- messageHandlers[message.type](message.data, (data) => {
- socket.sendMessage({
- id: message.id,
- data
- });
- })
- }
- });
-})
+const p2p = new P2PServer(send)
+p2p.listen()
//io.on('connection', function(socket)
//{
@@ -437,7 +414,7 @@ tcpServer.on('connection', (socket) => {
})
});
- onSocketMessage('searchTorrent', ({text, navigation} = {}, callback) => {
+ p2p.on('searchTorrent', ({text, navigation} = {}, callback) => {
if(!text)
return;
@@ -541,7 +518,7 @@ tcpServer.on('connection', (socket) => {
})
});
- onSocketMessage('searchFiles', ({text, navigation} = {}, callback) => {
+ p2p.on('searchFiles', ({text, navigation} = {}, callback) => {
if(!text)
return;
@@ -1046,86 +1023,6 @@ client.on('complete', function (metadata, infohash, rinfo) {
});
-const p2p = {
- peers: [],
- ignoreAddresses: [],
- add(address) {
- const { peers } = this
-
- if(peers.length > 10)
- return;
-
- if(address.port <= 1 || address.port > 65535)
- return;
-
- if(this.ignoreAddresses.includes(address.address))
- return;
-
- for(let peer of peers)
- {
- if(peer.address === address.address) {
- peer.port = address.port;
- return;
- }
- }
- this.connect(address)
- },
- connect(address)
- {
- this.peers.push(address)
- const socket = new JsonSocket(new net.Socket()); //Decorate a standard net.Socket with JsonSocket
- socket.on('connect', () => { //Don't send until we're connected
- // add to peers
- send('peer', this.peers.length)
- console.log('new peer', address)
-
- const callbacks = {}
- socket.on('message', (message) => {
- if(message.id && callbacks[message.id])
- {
- callbacks[message.id](message.data);
- delete callbacks[message.id];
- }
- });
-
- const emit = (type, data, callback) => {
- const id = Math.random().toString(36).substring(5)
- if(callback)
- callbacks[id] = callback;
- socket.sendMessage({
- id,
- type,
- data
- });
- }
- address.emit = emit
- });
-
- socket.on('close', () => {
- const index = this.peers.indexOf(address);
- if(index >= 0)
- {
- this.peers.splice(index, 1);
-
- console.log('close peer connection', address)
- send('peer', this.peers.length)
- }
- })
-
- socket.on('error', (err) => {})
-
- socket.connect(address.port, address.address);
- },
- emit(type, data, callback)
- {
- for(const peer of this.peers)
- {
- if(peer.emit)
- peer.emit(type, data, callback)
- }
- }
-}
-
const { STUN_BINDING_REQUEST, STUN_ATTR_XOR_MAPPED_ADDRESS } = stun.constants
const stunServer = stun.createServer()
const stunRequest = stun.createMessage(STUN_BINDING_REQUEST)
@@ -1139,11 +1036,6 @@ stunServer.once('bindingResponse', stunMsg => {
stunServer.send(stunRequest, 19302, 'stun.l.google.com')
spider.on('peer', (IPs) => {
- const { peers } = p2p;
-
- if(peers.length > 10)
- return
-
IPs.forEach(ip => p2p.add(ip))
})