Merge pull request #53 from valesi/tor

Add IRC option to publish Tor address
This commit is contained in:
Neil 2016-12-02 07:33:29 +09:00 committed by GitHub
commit 9f90ae049e
3 changed files with 84 additions and 32 deletions

View File

@ -86,12 +86,21 @@ BANDWIDTH_LIMIT - per-session periodic bandwith usage limit in bytes.
If you want IRC connectivity to advertise your node:
IRC - set to anything non-empty
IRC_NICK - the nick to use when connecting to IRC. The default is a
hash of REPORT_HOST. Either way 'E_' will be prepended.
REPORT_HOST - the host to advertise. Defaults to HOST.
REPORT_SSL_PORT - the SSL port to advertise. Defaults to SSL_PORT.
REPORT_TCP_PORT - the TCP port to advertise. Defaults to TCP_PORT.
IRC - set to anything non-empty
IRC_NICK - the nick to use when connecting to IRC. The default is a
hash of REPORT_HOST. Either way 'E_' will be prepended.
REPORT_HOST - the host to advertise. Defaults to HOST.
REPORT_TCP_PORT - the TCP port to advertise. Defaults to TCP_PORT.
'0' disables publishing the port.
REPORT_SSL_PORT - the SSL port to advertise. Defaults to SSL_PORT.
'0' disables publishing the port.
REPORT_HOST_TOR - Tor .onion address to advertise. Appends '_tor" to nick.
REPORT_TCP_PORT_TOR - the TCP port to advertise for Tor. Defaults to
REPORT_TCP_PORT, unless it is '0', then use TCP_PORT.
'0' disables publishing the port.
REPORT_SSL_PORT_TOR - the SSL port to advertise for Tor. Defaults to
REPORT_SSL_PORT, unless it is '0', then use SSL_PORT.
'0' disables publishing the port.
If synchronizing from the Genesis block your performance might change
by tweaking the following cache variables. Cache size is only checked
@ -124,4 +133,4 @@ FORCE_REORG - if set to a positive integer, it will simulate a reorg
of the blockchain for that number of blocks on startup.
Although it should fail gracefully if set to a value
greater than REORG_LIMIT, I do not recommend it as I have
not tried it and there is a chance your DB might corrupt.
not tried it and there is a chance your DB might corrupt.

View File

@ -51,11 +51,20 @@ class Env(LoggedClass):
self.max_session_subs = self.integer('MAX_SESSION_SUBS', 50000)
self.bandwidth_limit = self.integer('BANDWIDTH_LIMIT', 2000000)
# IRC
self.irc = self.default('IRC', False)
self.irc_nick = self.default('IRC_NICK', None)
self.report_tcp_port = self.integer('REPORT_TCP_PORT', self.tcp_port)
self.report_ssl_port = self.integer('REPORT_SSL_PORT', self.ssl_port)
self.report_host = self.default('REPORT_HOST', self.host)
self.irc_nick = self.default('IRC_NICK', None)
self.irc = self.default('IRC', False)
self.report_tcp_port_tor = self.integer('REPORT_TCP_PORT_TOR',
self.report_tcp_port
if self.report_tcp_port else
self.tcp_port)
self.report_ssl_port_tor = self.integer('REPORT_SSL_PORT_TOR',
self.report_ssl_port
if self.report_ssl_port else
self.ssl_port)
self.report_host_tor = self.default('REPORT_HOST_TOR', None)
# Debugging
self.force_reorg = self.integer('FORCE_REORG', 0)

View File

@ -20,12 +20,8 @@ from lib.hash import double_sha256
from lib.util import LoggedClass
def port_text(letter, port, default):
if not port:
return ''
if port == default:
return letter
return letter + str(port)
VERSION = '1.0'
DEFAULT_PORTS = {'t': 50001, 's': 50002}
class IRC(LoggedClass):
@ -37,22 +33,29 @@ class IRC(LoggedClass):
def __init__(self, env):
super().__init__()
tcp_text = port_text('t', env.report_tcp_port, 50001)
ssl_text = port_text('s', env.report_ssl_port, 50002)
# If this isn't something the client expects you won't appear
# in the client's network dialog box
self.env = env
version = '1.0'
self.real_name = '{} v{} {} {}'.format(env.report_host, version,
tcp_text, ssl_text)
# If this isn't something a peer or client expects
# then you won't appear in the client's network dialog box
irc_address = (env.coin.IRC_SERVER, env.coin.IRC_PORT)
self.channel = env.coin.IRC_CHANNEL
self.prefix = env.coin.IRC_PREFIX
self.clients = []
self.nick = '{}{}'.format(self.prefix,
env.irc_nick if env.irc_nick else
double_sha256(env.report_host.encode())
[:5].hex())
self.channel = env.coin.IRC_CHANNEL
self.irc_server = env.coin.IRC_SERVER
self.irc_port = env.coin.IRC_PORT
self.clients.append( IrcClient(irc_address, self.nick,
env.report_host,
env.report_tcp_port,
env.report_ssl_port) )
if env.report_host_tor:
self.clients.append( IrcClient(irc_address, self.nick + '_tor',
env.report_host_tor,
env.report_tcp_port_tor,
env.report_ssl_port_tor) )
self.peer_regexp = re.compile('({}[^!]*)!'.format(self.prefix))
self.peers = {}
@ -72,20 +75,23 @@ class IRC(LoggedClass):
async def join(self):
import irc.client as irc_client
self.logger.info('joining IRC with nick "{}" and real name "{}"'
.format(self.nick, self.real_name))
reactor = irc_client.Reactor()
for event in ['welcome', 'join', 'quit', 'kick', 'whoreply',
'namreply', 'disconnect']:
reactor.add_global_handler(event, getattr(self, 'on_' + event))
connection = reactor.server()
# Note: Multiple nicks in same channel will trigger duplicate events
for client in self.clients:
client.connection = reactor.server()
while True:
try:
connection.connect(self.irc_server, self.irc_port,
self.nick, ircname=self.real_name)
connection.set_keepalive(60)
for client in self.clients:
self.logger.info('Joining IRC in {} as "{}" with '
'real name "{}"'
.format(self.channel, client.nick,
client.realname))
client.connect()
while True:
reactor.process_once()
await asyncio.sleep(2)
@ -155,3 +161,31 @@ class IRC(LoggedClass):
self.peers[nick] = peer
except IndexError:
pass
class IrcClient(LoggedClass):
def __init__(self, irc_address, nick, host, tcp_port, ssl_port):
super().__init__()
self.irc_host, self.irc_port = irc_address
self.nick = nick
self.realname = IrcClient.create_realname(host, tcp_port, ssl_port)
self.connection = None
def connect(self, keepalive=60):
'''Connect this client to its IRC server'''
self.connection.connect(self.irc_host, self.irc_port, self.nick,
ircname=self.realname)
self.connection.set_keepalive(keepalive)
def create_realname(host, tcp_port, ssl_port):
def port_text(letter, port):
if letter in DEFAULT_PORTS and port == DEFAULT_PORTS[letter]:
return letter
else:
return letter + str(port)
tcp = ' ' + port_text('t', tcp_port) if tcp_port else ''
ssl = ' ' + port_text('s', ssl_port) if ssl_port else ''
return '{} v{}{}{}'.format(host, VERSION, tcp, ssl)