commit eb37d9008ec6cd460ddf352b98ed1fa14f454125 Author: Damian Johnson <ata...@torproject.org> Date: Wed Jul 29 10:17:20 2015 -0700
Move application resolution into the lines Our panel resolved applications, then populated attributes on the lines. Ewww! The tracker caches results so the lines can just retrieve values from that on-demand. While doing this realized past changs made it so we can't differentiate between 'unknown' and 'still resolving', so should fix that next. --- nyx/connections/conn_entry.py | 37 ++++++++++++------------- nyx/connections/conn_panel.py | 45 ++++--------------------------- nyx/util/tracker.py | 15 ++++++++++- test/util/tracker/port_usage_tracker.py | 6 ++--- 4 files changed, 39 insertions(+), 64 deletions(-) diff --git a/nyx/connections/conn_entry.py b/nyx/connections/conn_entry.py index d945182..fe18485 100644 --- a/nyx/connections/conn_entry.py +++ b/nyx/connections/conn_entry.py @@ -77,12 +77,6 @@ class ConnectionLine(entries.ConnectionPanelLine): self._possible_client = True self._possible_directory = True - # attributes for SOCKS, HIDDEN, and CONTROL connections - - self.application_name = None - self.application_pid = None - self.is_application_resolving = False - socks_ports = controller.get_ports(Listener.SOCKS, []) or_ports = controller.get_ports(Listener.OR, []) dir_ports = controller.get_ports(Listener.DIR, []) @@ -151,6 +145,16 @@ 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 @@ -195,13 +199,6 @@ class ConnectionLine(entries.ConnectionPanelLine): return my_listing - def is_unresolved_application(self): - """ - True if our display uses application information that hasn't yet been resolved. - """ - - return self.application_name is None and self.get_type() in (Category.SOCKS, Category.HIDDEN, Category.CONTROL) - def _get_listing_entry(self, width, current_time, listing_type): entry_type = self.get_type() @@ -354,16 +351,16 @@ class ConnectionLine(entries.ConnectionPanelLine): if self.get_type() in (Category.SOCKS, Category.HIDDEN, Category.CONTROL): display_label = '' + process = self.get_process() - if self.application_name: - if self.application_pid: - display_label = '%s (%s)' % (self.application_name, self.application_pid) + if process: + if process.pid: + display_label = '%s (%s)' % (process.name, process.pid) else: - display_label = self.application_name - elif self.is_application_resolving: - display_label = 'resolving...' + display_label = process.name else: - display_label = 'UNKNOWN' + # TODO: We should differentiate between 'resolving...' and 'unknown' + display_label = 'resolving...' 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 e40a431..5163ec9 100644 --- a/nyx/connections/conn_panel.py +++ b/nyx/connections/conn_panel.py @@ -13,7 +13,7 @@ import nyx.popups import nyx.util.tracker from nyx.connections import descriptor_popup, entries, conn_entry -from nyx.util import panel, tor_controller, tracker, ui_tools +from nyx.util import panel, tor_controller, ui_tools from stem.control import State from stem.util import conf, connection, enum @@ -115,10 +115,6 @@ class ConnectionPanel(panel.Panel, threading.Thread): self._last_resource_fetch = -1 - # resolver for the command/pid associated with SOCKS, HIDDEN, and CONTROL connections - - self._app_resolver = tracker.get_port_usage_tracker() - # mark the initially exitsing connection uptimes as being estimates for entry in self._entries: @@ -509,41 +505,10 @@ class ConnectionPanel(panel.Panel, threading.Thread): if not CONFIG['features.connection.resolveApps']: return - unresolved_lines = [l for l in self._entry_lines if isinstance(l, conn_entry.ConnectionLine) and l.is_unresolved_application()] - - # get the ports used for unresolved applications - app_ports = [] - for line in unresolved_lines: - app_ports.append(line.connection.local_port if line.get_type() == conn_entry.Category.HIDDEN else line.connection.remote_port) - - # Queue up resolution for the unresolved ports (skips if it's still working - # on the last query). - - if app_ports and not self._app_resolver.is_alive(): - self._app_resolver.get_processes_using_ports(app_ports) + for line in self._entry_lines: + if line.get_type() in (conn_entry.Category.SOCKS, conn_entry.Category.HIDDEN, conn_entry.Category.CONTROL): + app_ports.append(line.connection.local_port if line.get_type() == conn_entry.Category.HIDDEN else line.connection.remote_port) - # Fetches results. If the query finishes quickly then this is what we just - # asked for, otherwise these belong to an earlier resolution. - # - # The application resolver might have given up querying (for instance, if - # the lsof lookups aren't working on this platform or lacks permissions). - # The is_application_resolving flag lets the unresolved entries indicate if there's - # a lookup in progress for them or not. - - time.sleep(0.2) # TODO: previous resolver only blocked while awaiting a lookup - app_results = self._app_resolver.get_processes_using_ports(app_ports) - - for line in unresolved_lines: - is_local = line.get_type() == conn_entry.Category.HIDDEN - line_port = line.connection.local_port if is_local else line.connection.remote_port - - if line_port in app_results: - result = app_results[line_port] - - line.application_name = result.name - line.application_pid = result.pid - line.is_application_resolving = False - else: - line.is_application_resolving = self._app_resolver.is_alive + nyx.util.tracker.get_port_usage_tracker().query(app_ports) diff --git a/nyx/util/tracker.py b/nyx/util/tracker.py index f6219ad..5d9c81e 100644 --- a/nyx/util/tracker.py +++ b/nyx/util/tracker.py @@ -670,7 +670,20 @@ class PortUsageTracker(Daemon): self._processes_for_ports = {} self._failure_count = 0 # number of times in a row we've failed to get results - def get_processes_using_ports(self, ports): + def fetch(self, port): + """ + Provides the process running on the given port. This retrieves the results + from our cache, so it only works if we've already issued a query() request + for it and gotten results. + + :param int port: port number to look up + + :returns: **Process** using the given port, or **None** if it's unavailable + """ + + return self._processes_for_ports.get(port) + + def query(self, ports): """ Registers a given set of ports for further lookups, and returns the last set of 'port => process' mappings we retrieved. Note that this means that diff --git a/test/util/tracker/port_usage_tracker.py b/test/util/tracker/port_usage_tracker.py index 8528e69..41d88d0 100644 --- a/test/util/tracker/port_usage_tracker.py +++ b/test/util/tracker/port_usage_tracker.py @@ -91,10 +91,10 @@ class TestPortUsageTracker(unittest.TestCase): with PortUsageTracker(0.02) as daemon: time.sleep(0.01) - self.assertEqual({}, daemon.get_processes_using_ports([37277, 51849])) + self.assertEqual({}, daemon.query([37277, 51849])) time.sleep(0.04) - self.assertEqual({37277: 'python', 51849: 'tor'}, daemon.get_processes_using_ports([37277, 51849])) + self.assertEqual({37277: 'python', 51849: 'tor'}, daemon.query([37277, 51849])) @patch('nyx.util.tracker.tor_controller') @patch('nyx.util.tracker._process_for_ports') @@ -110,7 +110,7 @@ class TestPortUsageTracker(unittest.TestCase): time.sleep(0.05) self.assertEqual(0, daemon._failure_count) - daemon.get_processes_using_ports([37277, 51849]) + daemon.query([37277, 51849]) time.sleep(0.03) self.assertTrue(daemon.is_alive()) time.sleep(0.1) _______________________________________________ tor-commits mailing list tor-commits@lists.torproject.org https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits