Browse Source

Merge #1223: Choose directory node based on where nicks seen.

041ea4a Choose directory node based on where nicks seen. (Adam Gibson)
master
Adam Gibson 4 years ago
parent
commit
739f50c204
No known key found for this signature in database
GPG Key ID: 141001A1AF77F20B
  1. 49
      jmdaemon/jmdaemon/onionmc.py

49
jmdaemon/jmdaemon/onionmc.py

@ -3,6 +3,7 @@ from jmdaemon.protocol import COMMAND_PREFIX, JM_VERSION
from jmbase import get_log, JM_APP_NAME, JMHiddenService, stop_reactor from jmbase import get_log, JM_APP_NAME, JMHiddenService, stop_reactor
import json import json
import copy import copy
import random
from typing import Callable, Union, Tuple, List from typing import Callable, Union, Tuple, List
from twisted.internet import reactor, task, protocol from twisted.internet import reactor, task, protocol
from twisted.protocols import basic from twisted.protocols import basic
@ -116,6 +117,9 @@ class OnionCustomMessageDecodingError(Exception):
class InvalidLocationStringError(Exception): class InvalidLocationStringError(Exception):
pass pass
class OnionDirectoryPeerNotFound(Exception):
pass
class OnionCustomMessage(object): class OnionCustomMessage(object):
""" Encapsulates the messages passed over the wire """ Encapsulates the messages passed over the wire
to and from other onion peers to and from other onion peers
@ -586,6 +590,14 @@ class OnionDirectoryPeer(OnionPeer):
except OnionPeerConnectionError: except OnionPeerConnectionError:
reactor.callLater(self.delay, self.try_to_connect) reactor.callLater(self.delay, self.try_to_connect)
def register_connection(self) -> None:
self.messagechannel.update_directory_map(self, connected=True)
super().register_connection()
def register_disconnection(self) -> None:
self.messagechannel.update_directory_map(self, connected=False)
super().register_disconnection()
class OnionMessageChannel(MessageChannel): class OnionMessageChannel(MessageChannel):
""" Sends messages to other nodes of the same type over Tor """ Sends messages to other nodes of the same type over Tor
@ -687,6 +699,14 @@ class OnionMessageChannel(MessageChannel):
# the rpc connection calls are not using twisted) # the rpc connection calls are not using twisted)
self.wait_for_directories_loop = None self.wait_for_directories_loop = None
# this dict plays the same role as `active_channels` in `MessageChannelCollection`.
# it has structure {nick: set(),..} where set() has elements that are dicts:
# {OnionPeer: bool}.
# Entries get updated with changing connection status of directories,
# allowing us to decide where to send each message we want to send when we have no
# direct connection.
self.active_directories = {}
def info_callback(self, msg: str) -> None: def info_callback(self, msg: str) -> None:
log.info(msg) log.info(msg)
@ -787,11 +807,10 @@ class OnionMessageChannel(MessageChannel):
log.debug("Privmsg peer: {} but don't have peerid; " log.debug("Privmsg peer: {} but don't have peerid; "
"sending via directory.".format(nick)) "sending via directory.".format(nick))
try: try:
# TODO change this to redundant or switching peer_sendable = self.get_directory_for_nick(nick)
peer_sendable = self.get_connected_directory_peers()[0] except OnionDirectoryPeerNotFound:
except Exception as e:
log.warn("Failed to send privmsg because no " log.warn("Failed to send privmsg because no "
"directory peer is connected. Error: {}".format(repr(e))) "directory peer is connected.")
return return
self._send(peer_sendable, encoded_privmsg) self._send(peer_sendable, encoded_privmsg)
@ -965,6 +984,28 @@ class OnionMessageChannel(MessageChannel):
except Exception as e: except Exception as e:
log.debug("Invalid Joinmarket message: {}, error was: {}".format( log.debug("Invalid Joinmarket message: {}, error was: {}".format(
msgval, repr(e))) msgval, repr(e)))
# add the nick to the directories map, whether pubmsg or privmsg, but
# only if it passed the above syntax Exception catch:
if peer.directory and not self.self_as_peer.directory:
if from_nick not in self.active_directories:
self.active_directories[from_nick] = {}
self.active_directories[from_nick][peer] = True
def update_directory_map(self, p: OnionDirectoryPeer, connected: bool) -> None:
nicks = []
for nick in self.active_directories:
if p in self.active_directories[nick]:
nicks.append(nick)
for nick in nicks:
self.active_directories[nick][p] = connected
def get_directory_for_nick(self, nick: str) -> OnionDirectoryPeer:
if nick not in self.active_directories:
raise OnionDirectoryPeerNotFound
adn = self.active_directories[nick]
if len(adn) == 0:
raise OnionDirectoryPeerNotFound
return random.choice([x for x in list(adn) if adn[x] is True])
def forward_pubmsg_to_peers(self, msg: str, from_nick: str) -> None: def forward_pubmsg_to_peers(self, msg: str, from_nick: str) -> None:
""" Used by directory nodes currently. Takes a received """ Used by directory nodes currently. Takes a received

Loading…
Cancel
Save