feat(p2p): tunnels support for bad peers

This commit is contained in:
Alexey Kasyanchuk
2018-03-17 20:58:50 +03:00
parent 9f1a7eef83
commit 500b852209
5 changed files with 108 additions and 12 deletions

View File

@ -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;

View File

@ -113,10 +113,25 @@ 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>
</CardMedia> </CardMedia>
</Card> </Card>

View File

@ -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

View File

@ -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')
}) })

View File

@ -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