[tor-commits] [nyx/master] Differentiate between unknown and resolving apps

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


commit aba3b74ea029d5732af34192c55df101cf465fbf
Author: Damian Johnson <atagar at torproject.org>
Date:   Thu Jul 30 08:56:09 2015 -0700

    Differentiate between unknown and resolving apps
    
    Be a bit smarter about showing 'resolving...' when an application can't be
    determined and 'UNKNOWN' if it can't be determined.
---
 nyx/connections/conn_entry.py           |   26 +++++++------------------
 nyx/connections/conn_panel.py           |   10 +++++-----
 nyx/util/tracker.py                     |   32 ++++++++++++++++++++++++++++---
 test/util/tracker/port_usage_tracker.py |    6 +++---
 4 files changed, 44 insertions(+), 30 deletions(-)

diff --git a/nyx/connections/conn_entry.py b/nyx/connections/conn_entry.py
index fe18485..1eae80f 100644
--- a/nyx/connections/conn_entry.py
+++ b/nyx/connections/conn_entry.py
@@ -145,16 +145,6 @@ class ConnectionLine(entries.ConnectionPanelLine):
     nickname = nyx.util.tracker.get_consensus_tracker().get_relay_nickname(self.get_fingerprint())
     return nickname if nickname else default
 
-  def get_process(self):
-    """
-    Local process using this connection. This is only available for socks,
-    hidden service, and controller connections. This is **None** if the
-    application is either still being resolved or can't be determined.
-    """
-
-    port = self.connection.local_port if self.get_type() == Category.HIDDEN else self.connection.remote_port
-    return nyx.util.tracker.get_port_usage_tracker().fetch(port)
-
   def get_listing_entry(self, width, current_time, listing_type):
     """
     Provides the tuple list for this connection's listing. Lines are composed
@@ -350,17 +340,15 @@ class ConnectionLine(entries.ConnectionPanelLine):
     # for applications show the command/pid
 
     if self.get_type() in (Category.SOCKS, Category.HIDDEN, Category.CONTROL):
-      display_label = ''
-      process = self.get_process()
+      port = self.connection.local_port if self.get_type() == Category.HIDDEN else self.connection.remote_port
 
-      if process:
-        if process.pid:
-          display_label = '%s (%s)' % (process.name, process.pid)
-        else:
-          display_label = process.name
-      else:
-        # TODO: We should differentiate between 'resolving...' and 'unknown'
+      try:
+        process = nyx.util.tracker.get_port_usage_tracker().fetch(port)
+        display_label = '%s (%s)' % (process.name, process.pid) if process.pid else process.name
+      except nyx.util.tracker.UnresolvedResult:
         display_label = 'resolving...'
+      except nyx.util.tracker.UnknownApplication:
+        display_label = 'UNKNOWN'
 
       if len(display_label) < width:
         return ('%%-%is' % width) % display_label
diff --git a/nyx/connections/conn_panel.py b/nyx/connections/conn_panel.py
index b8f97ad..629a559 100644
--- a/nyx/connections/conn_panel.py
+++ b/nyx/connections/conn_panel.py
@@ -495,12 +495,12 @@ class ConnectionPanel(panel.Panel, threading.Thread):
       self._last_resource_fetch = current_resolution_count
 
       if CONFIG['features.connection.resolveApps']:
-        local_ports, remote_ports = []
+        local_ports, remote_ports = [], []
 
         for line in self._entry_lines:
-          if line.get_type() == conn_entry.Category.HIDDEN:
-            local_ports.append(line.connection.local_port)
-          elif line.get_type() in (conn_entry.Category.SOCKS, conn_entry.Category.CONTROL):
-            remote_ports.append(line.connection.remote_port)
+          if line.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:
+            remote_ports.append(line.connection.local_port)
 
         nyx.util.tracker.get_port_usage_tracker().query(local_ports, remote_ports)
diff --git a/nyx/util/tracker.py b/nyx/util/tracker.py
index 57562f5..88a53c3 100644
--- a/nyx/util/tracker.py
+++ b/nyx/util/tracker.py
@@ -91,6 +91,14 @@ Process = collections.namedtuple('Process', [
 ])
 
 
+class UnresolvedResult(Exception):
+  'Indicates the application being used by a port is still being determined.'
+
+
+class UnknownApplication(Exception):
+  'No application could be determined for this port.'
+
+
 def get_connection_tracker():
   """
   Singleton for tracking the connections established by tor.
@@ -253,7 +261,8 @@ def _process_for_ports(local_ports, remote_ports):
   :param list local_ports: local port numbers to look up
   :param list remote_ports: remote port numbers to look up
 
-  :returns: **dict** mapping the ports to the associated **Process**
+  :returns: **dict** mapping the ports to the associated **Process**, or
+    **None** if it can't be determined
 
   :raises: **IOError** if unsuccessful
   """
@@ -322,6 +331,9 @@ def _process_for_ports(local_ports, remote_ports):
       except ValueError as exc:
         raise IOError('unrecognized output from lsof (%s): %s' % (exc, line))
 
+    for unknown_port in set(local_ports).union(remote_ports).difference(results.keys()):
+      results[unknown_port] = None
+
     return results
 
   raise IOError('no results from lsof')
@@ -679,10 +691,24 @@ class PortUsageTracker(Daemon):
 
     :param int port: port number to look up
 
-    :returns: **Process** using the given port, or **None** if it's unavailable
+    :returns: **Process** using the given port
+
+    :raises:
+      * :class:`nyx.util.tracker.UnresolvedResult` if the application is still
+        being determined
+      * :class:`nyx.util.tracker.UnknownApplication` if the we tried to resolve
+        the application but it couldn't be determined
     """
 
-    return self._processes_for_ports.get(port)
+    try:
+      result = self._processes_for_ports[port]
+
+      if result is None:
+        raise UnknownApplication()
+      else:
+        return result
+    except KeyError:
+      raise UnresolvedResult()
 
   def query(self, local_ports, remote_ports):
     """
diff --git a/test/util/tracker/port_usage_tracker.py b/test/util/tracker/port_usage_tracker.py
index 64c4c09..31bdd4c 100644
--- a/test/util/tracker/port_usage_tracker.py
+++ b/test/util/tracker/port_usage_tracker.py
@@ -47,8 +47,8 @@ class TestPortUsageTracker(unittest.TestCase):
   @patch('nyx.util.tracker.system.call', Mock(return_value = LSOF_OUTPUT.split('\n')))
   def test_process_for_ports(self):
     self.assertEqual({}, _process_for_ports([], []))
-    self.assertEqual({}, _process_for_ports([80, 443], []))
-    self.assertEqual({}, _process_for_ports([], [80, 443]))
+    self.assertEqual({80: None, 443: None}, _process_for_ports([80, 443], []))
+    self.assertEqual({80: None, 443: None}, _process_for_ports([], [80, 443]))
 
     self.assertEqual({37277: Process(2462, 'python'), 51849: Process(2001, 'tor')}, _process_for_ports([37277], [51849]))
 
@@ -63,7 +63,7 @@ class TestPortUsageTracker(unittest.TestCase):
 
     for test_input in test_inputs:
       call_mock.return_value = test_input.split('\n')
-      self.assertEqual({}, _process_for_ports([80], [443]))
+      self.assertEqual({80: None, 443: None}, _process_for_ports([80], [443]))
 
     # Isuses that are reported as errors.
 





More information about the tor-commits mailing list