[tor-commits] [nyx/master] Move connection type to be tracked by entity

atagar at torproject.org atagar at torproject.org
Tue Sep 22 17:08:40 UTC 2015


commit 6f7eac497a9d4062ff18d6a0b12791099e977f2c
Author: Damian Johnson <atagar at 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





More information about the tor-commits mailing list