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: If you want IRC connectivity to advertise your node:
IRC - set to anything non-empty IRC - set to anything non-empty
IRC_NICK - the nick to use when connecting to IRC. The default is a IRC_NICK - the nick to use when connecting to IRC. The default is a
hash of REPORT_HOST. Either way 'E_' will be prepended. hash of REPORT_HOST. Either way 'E_' will be prepended.
REPORT_HOST - the host to advertise. Defaults to HOST. 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.
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 If synchronizing from the Genesis block your performance might change
by tweaking the following cache variables. Cache size is only checked 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. of the blockchain for that number of blocks on startup.
Although it should fail gracefully if set to a value Although it should fail gracefully if set to a value
greater than REORG_LIMIT, I do not recommend it as I have 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.max_session_subs = self.integer('MAX_SESSION_SUBS', 50000)
self.bandwidth_limit = self.integer('BANDWIDTH_LIMIT', 2000000) self.bandwidth_limit = self.integer('BANDWIDTH_LIMIT', 2000000)
# IRC # 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_tcp_port = self.integer('REPORT_TCP_PORT', self.tcp_port)
self.report_ssl_port = self.integer('REPORT_SSL_PORT', self.ssl_port) self.report_ssl_port = self.integer('REPORT_SSL_PORT', self.ssl_port)
self.report_host = self.default('REPORT_HOST', self.host) self.report_host = self.default('REPORT_HOST', self.host)
self.irc_nick = self.default('IRC_NICK', None) self.report_tcp_port_tor = self.integer('REPORT_TCP_PORT_TOR',
self.irc = self.default('IRC', False) 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 # Debugging
self.force_reorg = self.integer('FORCE_REORG', 0) 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 from lib.util import LoggedClass
def port_text(letter, port, default): VERSION = '1.0'
if not port: DEFAULT_PORTS = {'t': 50001, 's': 50002}
return ''
if port == default:
return letter
return letter + str(port)
class IRC(LoggedClass): class IRC(LoggedClass):
@ -37,22 +33,29 @@ class IRC(LoggedClass):
def __init__(self, env): def __init__(self, env):
super().__init__() 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 self.env = env
version = '1.0'
self.real_name = '{} v{} {} {}'.format(env.report_host, version, # If this isn't something a peer or client expects
tcp_text, ssl_text) # 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.prefix = env.coin.IRC_PREFIX
self.clients = []
self.nick = '{}{}'.format(self.prefix, self.nick = '{}{}'.format(self.prefix,
env.irc_nick if env.irc_nick else env.irc_nick if env.irc_nick else
double_sha256(env.report_host.encode()) double_sha256(env.report_host.encode())
[:5].hex()) [:5].hex())
self.channel = env.coin.IRC_CHANNEL self.clients.append( IrcClient(irc_address, self.nick,
self.irc_server = env.coin.IRC_SERVER env.report_host,
self.irc_port = env.coin.IRC_PORT 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.peer_regexp = re.compile('({}[^!]*)!'.format(self.prefix))
self.peers = {} self.peers = {}
@ -72,20 +75,23 @@ class IRC(LoggedClass):
async def join(self): async def join(self):
import irc.client as irc_client 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() reactor = irc_client.Reactor()
for event in ['welcome', 'join', 'quit', 'kick', 'whoreply', for event in ['welcome', 'join', 'quit', 'kick', 'whoreply',
'namreply', 'disconnect']: 'namreply', 'disconnect']:
reactor.add_global_handler(event, getattr(self, 'on_' + event)) 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: while True:
try: try:
connection.connect(self.irc_server, self.irc_port, for client in self.clients:
self.nick, ircname=self.real_name) self.logger.info('Joining IRC in {} as "{}" with '
connection.set_keepalive(60) 'real name "{}"'
.format(self.channel, client.nick,
client.realname))
client.connect()
while True: while True:
reactor.process_once() reactor.process_once()
await asyncio.sleep(2) await asyncio.sleep(2)
@ -155,3 +161,31 @@ class IRC(LoggedClass):
self.peers[nick] = peer self.peers[nick] = peer
except IndexError: except IndexError:
pass 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)