feat(p2p): tunnels support for bad peers
This commit is contained in:
@ -105,6 +105,18 @@ class App extends Component {
|
|||||||
this.forceUpdate()
|
this.forceUpdate()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
window.torrentSocket.emit('p2pStatus', (status) => {
|
||||||
|
if(status == 0)
|
||||||
|
return
|
||||||
|
|
||||||
|
window.p2pStatus = status
|
||||||
|
this.forceUpdate()
|
||||||
|
})
|
||||||
|
window.torrentSocket.on('p2pStatus', (status) => {
|
||||||
|
window.p2pStatus = status
|
||||||
|
this.forceUpdate()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
appReady = false;
|
appReady = false;
|
||||||
|
@ -113,8 +113,23 @@ const Header = (props) => {
|
|||||||
{
|
{
|
||||||
!window.currentWindow.isModal()
|
!window.currentWindow.isModal()
|
||||||
&&
|
&&
|
||||||
<div className='fs0-85 pad0-75' style={{marginLeft: 'auto', marginTop: '-10px', color: window.peers > 0 ? '#42f445' : 'white'}}>
|
<div className='fs0-85 pad0-75 column' style={{marginLeft: 'auto', marginTop: '-10px', color: window.peers > 0 ? '#42f445' : 'white'}}>
|
||||||
rats peers: {window.peers} {window.peers > 0 ? ' (p2p rats search enabled)' : ' (p2p rats search not available at this moment)'}
|
<div>rats peers: {window.peers} {window.peers > 0 ? ' (p2p rats search enabled)' : ' (p2p rats search not available at this moment)'}</div>
|
||||||
|
{
|
||||||
|
window.p2pStatus == 0
|
||||||
|
&&
|
||||||
|
<div style={{color: 'red'}}>extenal connection not avaible (check port forwarding)</div>
|
||||||
|
}
|
||||||
|
{
|
||||||
|
window.p2pStatus == 1
|
||||||
|
&&
|
||||||
|
<div style={{color: 'orange'}}>port not available, but connections redirected</div>
|
||||||
|
}
|
||||||
|
{
|
||||||
|
window.p2pStatus == 2
|
||||||
|
&&
|
||||||
|
<div style={{color: 'green'}}>port connections fully avaible</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
|
import ssh from './ssh'
|
||||||
const config = require('./config');
|
const config = require('./config');
|
||||||
const net = require('net')
|
const net = require('net')
|
||||||
const JsonSocket = require('json-socket')
|
const JsonSocket = require('json-socket')
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
|
const isPortReachable = require('./isPortReachable')
|
||||||
|
|
||||||
class p2p {
|
class p2p {
|
||||||
peers = []
|
peers = []
|
||||||
ignoreAddresses = []
|
ignoreAddresses = []
|
||||||
messageHandlers = {}
|
messageHandlers = {}
|
||||||
|
externalPeers = []
|
||||||
size = 0
|
size = 0
|
||||||
|
p2pStatus = 0
|
||||||
|
|
||||||
constructor(send = () => {})
|
constructor(send = () => {})
|
||||||
{
|
{
|
||||||
@ -99,6 +103,50 @@ class p2p {
|
|||||||
this.tcpServer.listen(config.spiderPort, '0.0.0.0');
|
this.tcpServer.listen(config.spiderPort, '0.0.0.0');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkPortAndRedirect(address, port) {
|
||||||
|
isPortReachable(port, {host: address}).then((isAvailable) => {
|
||||||
|
this.p2pStatus = isAvailable ? 2 : 0
|
||||||
|
this.send('p2pStatus', this.p2pStatus)
|
||||||
|
|
||||||
|
// all ok don't need to start any ssh tunnels
|
||||||
|
if(isAvailable)
|
||||||
|
{
|
||||||
|
console.log('tcp p2p port is reachable - all ok')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
console.log('tcp p2p port is unreachable - try ssh tunnel')
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!this.encryptor)
|
||||||
|
{
|
||||||
|
console.error('something wrong with encryptor')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let remoteHost = '03de848286b8fbe6e775e6601c3bcfb9b71dfddcacb861b061458ce5e4020a15a649aabef88234d2af01ead4276a6de1YlqiJBlXCmoA7TpnbRuSRHNDsIBLlZ9McbovKJXHtAA='
|
||||||
|
|
||||||
|
ssh(config.spiderPort, this.encryptor.decrypt(remoteHost), 'relay', 'relaymytrf', (selfPeer) => {
|
||||||
|
if(!selfPeer)
|
||||||
|
{
|
||||||
|
this.p2pStatus = 0
|
||||||
|
this.send('p2pStatus', this.p2pStatus)
|
||||||
|
this.externalPeers = []
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('ssh tunnel success, redirect peers to ssh')
|
||||||
|
|
||||||
|
this.p2pStatus = 1
|
||||||
|
this.send('p2pStatus', this.p2pStatus)
|
||||||
|
this.ignore(selfPeer)
|
||||||
|
this.emit('peer', selfPeer)
|
||||||
|
this.externalPeers = [selfPeer] // add external peers and tell this on every connection
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
on(type, callback) {
|
on(type, callback) {
|
||||||
this.messageHandlers[type] = callback
|
this.messageHandlers[type] = callback
|
||||||
}
|
}
|
||||||
@ -112,13 +160,24 @@ class p2p {
|
|||||||
if(address.port <= 1 || address.port > 65535)
|
if(address.port <= 1 || address.port > 65535)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(this.ignoreAddresses.includes(address.address))
|
// check ignore
|
||||||
return;
|
for(const ignoreAddress of this.ignoreAddresses)
|
||||||
|
{
|
||||||
|
if(typeof ignoreAddress === 'object')
|
||||||
|
{
|
||||||
|
if(ignoreAddress.address === address.address && ignoreAddress.port === address.port)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(ignoreAddress === address.address)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(let peer of peers)
|
for(let peer of peers)
|
||||||
{
|
{
|
||||||
if(peer.address === address.address) {
|
if(peer.address === address.address && peer.port === address.port) {
|
||||||
peer.port = address.port;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -156,7 +215,7 @@ class p2p {
|
|||||||
emit('protocol', {
|
emit('protocol', {
|
||||||
protocol: 'rats',
|
protocol: 'rats',
|
||||||
port: config.spiderPort,
|
port: config.spiderPort,
|
||||||
peers: this.peersList().slice(0, 4).map(peer => ({address: peer.address, port: peer.port}))
|
peers: this.peersList().slice(0, 4).map(peer => ({address: peer.address, port: peer.port})).concat(this.externalPeers) // also add external peers
|
||||||
}, (data) => {
|
}, (data) => {
|
||||||
if(!data || data.protocol != 'rats')
|
if(!data || data.protocol != 'rats')
|
||||||
return
|
return
|
||||||
|
@ -259,6 +259,7 @@ setInterval(() => {
|
|||||||
}, 24 * 60 * 60 * 1000);
|
}, 24 * 60 * 60 * 1000);
|
||||||
|
|
||||||
const p2p = new P2PServer(send)
|
const p2p = new P2PServer(send)
|
||||||
|
p2p.encryptor = encryptor
|
||||||
p2p.listen()
|
p2p.listen()
|
||||||
// load initial peers
|
// load initial peers
|
||||||
if(dataDirectory && fs.existsSync(dataDirectory + '/peers.p2p'))
|
if(dataDirectory && fs.existsSync(dataDirectory + '/peers.p2p'))
|
||||||
@ -724,6 +725,14 @@ if(config.p2pBootstrap)
|
|||||||
callback(p2p.size)
|
callback(p2p.size)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
recive('p2pStatus', (callback) =>
|
||||||
|
{
|
||||||
|
if(typeof callback != 'function')
|
||||||
|
return;
|
||||||
|
|
||||||
|
callback(p2p.p2pStatus)
|
||||||
|
});
|
||||||
|
|
||||||
recive('config', (callback) =>
|
recive('config', (callback) =>
|
||||||
{
|
{
|
||||||
if(typeof callback != 'function')
|
if(typeof callback != 'function')
|
||||||
@ -1213,6 +1222,9 @@ checkInternet((connected) => {
|
|||||||
|
|
||||||
console.log('p2p stun ignore my address', address)
|
console.log('p2p stun ignore my address', address)
|
||||||
p2p.ignore(address)
|
p2p.ignore(address)
|
||||||
|
|
||||||
|
// check port avalibility
|
||||||
|
p2p.checkPortAndRedirect(address, config.spiderPort)
|
||||||
})
|
})
|
||||||
stunServer.send(stunRequest, 19302, 'stun.l.google.com')
|
stunServer.send(stunRequest, 19302, 'stun.l.google.com')
|
||||||
})
|
})
|
||||||
|
@ -19,13 +19,13 @@ const startSSH = (port, host, user, password, callback) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const options = [
|
const options = [
|
||||||
|
'-N',
|
||||||
'-T',
|
'-T',
|
||||||
'-R', `0.0.0.0:${remotePort}:127.0.0.1:${port}`,
|
'-R', `0.0.0.0:${remotePort}:127.0.0.1:${port}`,
|
||||||
`${user}@${host}`,
|
`${user}@${host}`,
|
||||||
'-pw', password,
|
'-pw', password,
|
||||||
'-v'
|
'-v'
|
||||||
]
|
]
|
||||||
console.log(options)
|
|
||||||
|
|
||||||
const ssh = spawn(appPath('plink'), options)
|
const ssh = spawn(appPath('plink'), options)
|
||||||
|
|
||||||
@ -56,15 +56,13 @@ const startSSH = (port, host, user, password, callback) => {
|
|||||||
if(data.includes('Password authentication failed'))
|
if(data.includes('Password authentication failed'))
|
||||||
{
|
{
|
||||||
ssh.kill()
|
ssh.kill()
|
||||||
if(callback)
|
|
||||||
callback(false)
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ssh.on('close', (code, signal) => {
|
ssh.on('close', (code, signal) => {
|
||||||
|
console.log(`ssh closed with code ${code} and signal ${signal}`)
|
||||||
if(callback)
|
if(callback)
|
||||||
callback(false)
|
callback(false)
|
||||||
console.log(`ssh closed with code ${code} and signal ${signal}`)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return ssh
|
return ssh
|
||||||
|
Reference in New Issue
Block a user