commit 6f7eac497a9d4062ff18d6a0b12791099e977f2c Author: Damian Johnson atagar@torproject.org Date: Sat Aug 1 16:51:27 2015 -0700
Move connection type to be tracked by entity
Our get_type() method is a method on individual lines rather than the parent entity, which is weird. All lines always share the same type, and we almost always fetch it from entites via...
my_entity.get_lines()[0].get_type()
Moving it to be tracked on the entity instead, and lines just report whatever its parent has. --- nyx/connections/circ_entry.py | 16 +++----- nyx/connections/conn_entry.py | 81 ++--------------------------------------- nyx/connections/conn_panel.py | 10 ++--- nyx/connections/entries.py | 73 ++++++++++++++++++++++++++++++++----- 4 files changed, 77 insertions(+), 103 deletions(-)
diff --git a/nyx/connections/circ_entry.py b/nyx/connections/circ_entry.py index 94a0196..7d3fc8d 100644 --- a/nyx/connections/circ_entry.py +++ b/nyx/connections/circ_entry.py @@ -24,8 +24,8 @@ class CircHeaderLine(conn_entry.ConnectionLine): lines except that its etc field has circuit attributes. """
- def __init__(self, circ): - conn_entry.ConnectionLine.__init__(self, nyx.util.tracker.Connection(entries.to_unix_time(circ.created), False, '127.0.0.1', 0, '0.0.0.0', 0, 'tcp'), False, False) + def __init__(self, entry, circ): + conn_entry.ConnectionLine.__init__(self, entry, nyx.util.tracker.Connection(entries.to_unix_time(circ.created), False, '127.0.0.1', 0, '0.0.0.0', 0, 'tcp'), False, False) self.circuit_id = circ.id self.purpose = circ.purpose.capitalize() self.is_built = False @@ -33,7 +33,7 @@ class CircHeaderLine(conn_entry.ConnectionLine): self._remote_fingerprint = None
def set_exit(self, exit_address, exit_port, exit_fingerprint): - conn_entry.ConnectionLine.__init__(self, nyx.util.tracker.Connection(self._timestamp, False, '127.0.0.1', 0, exit_address, exit_port, 'tcp'), False, False) + conn_entry.ConnectionLine.__init__(self, self._entry, nyx.util.tracker.Connection(self._timestamp, False, '127.0.0.1', 0, exit_address, exit_port, 'tcp'), False, False) self.is_built = True self._remote_fingerprint = exit_fingerprint
@@ -43,9 +43,6 @@ class CircHeaderLine(conn_entry.ConnectionLine): else: return conn_entry.ConnectionLine.get_fingerprint(self, default)
- def get_type(self): - return conn_entry.Category.CIRCUIT - def get_destination_label(self, max_length, include_locale = False): if not self.is_built: return 'Building...' @@ -83,8 +80,8 @@ class CircLine(conn_entry.ConnectionLine): caching, etc). """
- def __init__(self, remote_address, remote_port, remote_fingerprint, placement_label, timestamp): - conn_entry.ConnectionLine.__init__(self, nyx.util.tracker.Connection(timestamp, False, '127.0.0.1', 0, remote_address, remote_port, 'tcp')) + def __init__(self, entry, remote_address, remote_port, remote_fingerprint, placement_label, timestamp): + conn_entry.ConnectionLine.__init__(self, entry, nyx.util.tracker.Connection(timestamp, False, '127.0.0.1', 0, remote_address, remote_port, 'tcp')) self._remote_fingerprint = remote_fingerprint self.placement_label = placement_label self.include_port = False @@ -96,9 +93,6 @@ class CircLine(conn_entry.ConnectionLine): def get_fingerprint(self, default = None): self._remote_fingerprint
- def get_type(self): - return conn_entry.Category.CIRCUIT - def get_listing_prefix(self): if self.is_last: return (ord(' '), curses.ACS_LLCORNER, curses.ACS_HLINE, ord(' ')) diff --git a/nyx/connections/conn_entry.py b/nyx/connections/conn_entry.py index f8593ff..381afec 100644 --- a/nyx/connections/conn_entry.py +++ b/nyx/connections/conn_entry.py @@ -11,7 +11,6 @@ import nyx.util.ui_tools from nyx.util import tor_controller from nyx.connections import entries
-from stem.control import Listener from stem.util import conf, connection, enum, str_tools
# Connection Categories: @@ -59,13 +58,12 @@ class ConnectionLine(entries.ConnectionPanelLine): Display component of the ConnectionEntry. """
- def __init__(self, conn, include_port=True, include_expanded_addresses=True): + def __init__(self, entry, conn, include_port=True, include_expanded_addresses=True): entries.ConnectionPanelLine.__init__(self)
+ self._entry = entry self.connection = conn
- self.cached_type = None - # includes the port or expanded ip address field when displaying listing # information if true
@@ -225,80 +223,7 @@ class ConnectionLine(entries.ConnectionPanelLine): return False
def get_type(self): - """ - Provides our best guess at the current type of the connection. This - depends on consensus results, our current client circuits, etc. Results - are cached until this entry's display is reset. - """ - - # caches both to simplify the calls and to keep the type consistent until - # we want to reflect changes - - if not self.cached_type: - controller = tor_controller() - - my_hidden_service_ports = [] # ports belonging to our hidden service configuation - - for hs_config in controller.get_hidden_service_conf({}).values(): - my_hidden_service_ports += [entry[2] for entry in hs_config['HiddenServicePort']] - - if self.connection.local_port in controller.get_ports(Listener.OR, []): - base_type = Category.INBOUND - elif self.connection.local_port in controller.get_ports(Listener.DIR, []): - base_type = Category.INBOUND - elif self.connection.local_port in controller.get_ports(Listener.SOCKS, []): - base_type = Category.SOCKS - elif self.connection.remote_port in my_hidden_service_ports: - base_type = Category.HIDDEN - elif self.connection.local_port in controller.get_ports(Listener.CONTROL, []): - base_type = Category.CONTROL - else: - # Currently the only non-static categories are OUTBOUND vs... - # - EXIT since this depends on the current consensus - # - CIRCUIT if this is likely to belong to our guard usage - # - DIRECTORY if this is a single-hop circuit (directory mirror?) - # - # The exitability, circuits, and fingerprints are all cached by the - # tor_tools util keeping this a quick lookup. - - base_type = Category.OUTBOUND - destination_fingerprint = nyx.util.tracker.get_consensus_tracker().get_relay_fingerprint(self.connection.remote_address, self.connection.remote_port) - - if not destination_fingerprint: - # Not a known relay. This might be an exit connection. - - exit_policy = controller.get_exit_policy(None) - port = self.connection.remote_port if self.connection.remote_port else None - - if exit_policy and exit_policy.can_exit_to(self.connection.remote_address, port): - self.cached_type = Category.EXIT - else: - # This belongs to a known relay. If we haven't eliminated ourselves as - # a possible client or directory connection then check if it still - # holds true. - - my_circuits = controller.get_circuits([]) - - # Checks that this belongs to the first hop in a circuit that's - # either unestablished or longer than a single hop (ie, anything but - # a built 1-hop connection since those are most likely a directory - # mirror). - - for circ in my_circuits: - if circ.path and circ.path[0][0] == destination_fingerprint and (circ.status != 'BUILT' or len(circ.path) > 1): - self.cached_type = Category.CIRCUIT # matched a probable guard connection - - if not self.cached_type: - # Checks if we match a built, single hop circuit. - - for circ in my_circuits: - if circ.path and circ.path[0][0] == destination_fingerprint and circ.status == 'BUILT' and len(circ.path) == 1: - self.cached_type = Category.DIRECTORY - - if not self.cached_type: - self.cached_type = base_type - - return self.cached_type + return self._entry.get_type()
def get_etc_content(self, width, listing_type): """ diff --git a/nyx/connections/conn_panel.py b/nyx/connections/conn_panel.py index c16f874..7d06abe 100644 --- a/nyx/connections/conn_panel.py +++ b/nyx/connections/conn_panel.py @@ -438,7 +438,7 @@ class ConnectionPanel(panel.Panel, threading.Thread): elif not entries: title = 'Connections:' else: - counts = collections.Counter([entry.get_lines()[0].get_type() for entry in entries]) + counts = collections.Counter([entry.get_type() for entry in entries]) count_labels = ['%i %s' % (counts[category], category.lower()) for category in conn_entry.Category if counts[category]] title = 'Connections (%s):' % ', '.join(count_labels)
@@ -481,12 +481,12 @@ class ConnectionPanel(panel.Panel, threading.Thread): for entry in new_entries: entry_line = entry.get_lines()[0]
- if entry_line.is_private() and entry_line.get_type() == conn_entry.Category.INBOUND: + if entry_line.is_private() and entry.get_type() == conn_entry.Category.INBOUND: client_locale = entry_line.get_locale(None)
if client_locale: self._client_locale_usage[client_locale] = self._client_locale_usage.get(client_locale, 0) + 1 - elif entry_line.get_type() == conn_entry.Category.EXIT: + elif entry.get_type() == conn_entry.Category.EXIT: exit_port = entry_line.connection.remote_port self._exit_port_usage[exit_port] = self._exit_port_usage.get(exit_port, 0) + 1
@@ -501,9 +501,9 @@ class ConnectionPanel(panel.Panel, threading.Thread): for entry in new_entries: line = entry.get_lines()[0]
- if line.get_type() in (conn_entry.Category.SOCKS, conn_entry.Category.CONTROL): + if entry.get_type() in (conn_entry.Category.SOCKS, conn_entry.Category.CONTROL): local_ports.append(line.connection.remote_port) - elif line.get_type() == conn_entry.Category.HIDDEN: + elif entry.get_type() == conn_entry.Category.HIDDEN: remote_ports.append(line.connection.local_port)
nyx.util.tracker.get_port_usage_tracker().query(local_ports, remote_ports) diff --git a/nyx/connections/entries.py b/nyx/connections/entries.py index fa4e71f..7ea3321 100644 --- a/nyx/connections/entries.py +++ b/nyx/connections/entries.py @@ -6,6 +6,9 @@ consists of in the listing.
import datetime
+from nyx.util import tor_controller + +from stem.control import Listener from stem.util import enum
# attributes we can list entries by @@ -39,25 +42,27 @@ def to_unix_time(dt):
class ConnectionPanelEntry: - def __init__(self, start_time): + def __init__(self, connection_type, start_time): self.lines = [] - self.start_time = start_time + self._connection_type = connection_type + self._start_time = start_time
@staticmethod def from_connection(conn): import nyx.connections.conn_entry
- entry = ConnectionPanelEntry(conn.start_time) - entry.lines = [nyx.connections.conn_entry.ConnectionLine(conn)] + entry = ConnectionPanelEntry(get_type(conn), conn.start_time) + entry.lines = [nyx.connections.conn_entry.ConnectionLine(entry, conn)] return entry
@staticmethod def from_circuit(circ): import nyx.connections.circ_entry + import nyx.connections.conn_entry import nyx.util.tracker
- entry = ConnectionPanelEntry(to_unix_time(circ.created)) - entry.lines = [nyx.connections.circ_entry.CircHeaderLine(circ)] + entry = ConnectionPanelEntry(nyx.connections.conn_entry.Category.CIRCUIT, to_unix_time(circ.created)) + entry.lines = [nyx.connections.circ_entry.CircHeaderLine(entry, circ)]
path = [path_entry[0] for path_entry in circ.path]
@@ -77,12 +82,20 @@ class ConnectionPanelEntry:
placement_label = '%i / %s' % (i + 1, placement_type)
- entry.lines.append(nyx.connections.circ_entry.CircLine(relay_ip, relay_port, relay_fingerprint, placement_label, to_unix_time(circ.created))) + entry.lines.append(nyx.connections.circ_entry.CircLine(entry, relay_ip, relay_port, relay_fingerprint, placement_label, to_unix_time(circ.created)))
entry.lines[-1].is_last = True
return entry
+ def get_type(self): + """ + Provides our best guess at the current type of the connection. This + depends on consensus results, our current client circuits, etc. + """ + + return self._connection_type + def get_lines(self): """ Provides the individual lines in the connection listing. @@ -128,9 +141,9 @@ class ConnectionPanelEntry: return 'z' * 20 # orders at the end elif attr == SortAttr.CATEGORY: import nyx.connections.conn_entry - return nyx.connections.conn_entry.Category.index_of(connection_line.get_type()) + return nyx.connections.conn_entry.Category.index_of(self.get_type()) elif attr == SortAttr.UPTIME: - return self.start_time + return self._start_time elif attr == SortAttr.COUNTRY: if connection_line.connection.is_private_address(self.lines[0].connection.remote_address): return '' @@ -214,3 +227,45 @@ class ConnectionPanelLine: def _get_details(self, width): # implementation of get_details return [] + + +def get_type(connection): + import nyx.connections.conn_entry + import nyx.util.tracker + + controller = tor_controller() + + my_hidden_service_ports = [] # ports belonging to our hidden service configuation + + for hs_config in controller.get_hidden_service_conf({}).values(): + my_hidden_service_ports += [entry[2] for entry in hs_config['HiddenServicePort']] + + if connection.local_port in controller.get_ports(Listener.OR, []): + return nyx.connections.conn_entry.Category.INBOUND + elif connection.local_port in controller.get_ports(Listener.DIR, []): + return nyx.connections.conn_entry.Category.INBOUND + elif connection.local_port in controller.get_ports(Listener.SOCKS, []): + return nyx.connections.conn_entry.Category.SOCKS + elif connection.remote_port in my_hidden_service_ports: + return nyx.connections.conn_entry.Category.HIDDEN + elif connection.local_port in controller.get_ports(Listener.CONTROL, []): + return nyx.connections.conn_entry.Category.CONTROL + else: + destination_fingerprint = nyx.util.tracker.get_consensus_tracker().get_relay_fingerprint(connection.remote_address, connection.remote_port) + + if not destination_fingerprint: + # Not a known relay. This might be an exit connection. + + exit_policy = controller.get_exit_policy(None) + + if exit_policy and exit_policy.can_exit_to(connection.remote_address, connection.remote_port): + return nyx.connections.conn_entry.Category.EXIT + else: + for circ in controller.get_circuits([]): + if circ.path[0][0] == destination_fingerprint and circ.status == 'BUILT': + # Tor builds one-hop circuits to retrieve directory information. + # If longer this is likely a connection to a guard. + + return nyx.connections.conn_entry.Category.DIRECTORY if len(circ.path) == 1 else nyx.connections.conn_entry.Category.CIRCUIT + + return nyx.connections.conn_entry.Category.OUTBOUND
tor-commits@lists.torproject.org