[stem/master] Trailing whitespace broke 'ss' connection resolution

commit 8a00dcb0cd1bf00e6fc5ea315de555882a175683 Author: Damian Johnson <atagar@torproject.org> Date: Fri Sep 11 15:56:37 2020 -0700 Trailing whitespace broke 'ss' connection resolution Some platforms append trailing whitespace to the output of the 'ss' command. Caught thanks to toralf... https://github.com/torproject/stem/issues/46 Determined the problem by running the following against toralf's output... from stem.util.connection import Resolver, get_connections from unittest.mock import patch with open('ss-nptu.log') as ss_file: ss_output = ss_file.read() with patch('stem.util.system.call') as call_mock: call_mock.return_value = ss_output.split('\n') print('parsed %i connections' % len(get_connections(Resolver.SS, process_pid = 2238, process_name = 'tor'))) Before: % python3.7 demo.py Traceback (most recent call last): File "demo.py", line 12, in <module> print('parsed %i connections' % len(get_connections(Resolver.SS, process_pid = 2238, process_name = 'tor'))) File "/home/atagar/Desktop/stem/stem/util/connection.py", line 333, in get_connections raise OSError('No results found using: %s' % resolver_command) OSError: No results found using: ss -nptu After: % python3.7 demo.py parsed 8114 connections --- docs/change_log.rst | 4 ++++ stem/util/connection.py | 2 +- test/settings.cfg | 1 + test/unit/util/connection.py | 19 +++++++++++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/docs/change_log.rst b/docs/change_log.rst index 5a9a8928..cc830d6c 100644 --- a/docs/change_log.rst +++ b/docs/change_log.rst @@ -67,6 +67,10 @@ The following are only available within Stem's `git repository * *transport* lines within extrainfo descriptors failed to validate + * **Utilities** + + * *ss* connection resolver failed on platforms that append whitespace (:ticket:`46`) + * **Installation** * Migrated from distutil to setuptools diff --git a/stem/util/connection.py b/stem/util/connection.py index a83922f7..2198d526 100644 --- a/stem/util/connection.py +++ b/stem/util/connection.py @@ -126,7 +126,7 @@ RESOLVER_FILTER = { Resolver.NETSTAT_WINDOWS: '^\\s*{protocol}\\s+{local}\\s+{remote}\\s+ESTABLISHED\\s+{pid}\\s*$', # tcp ESTAB 0 0 192.168.0.20:44415 38.229.79.2:443 users:(("tor",15843,9)) - Resolver.SS: '^{protocol}\\s+ESTAB\\s+.*\\s+{local}\\s+{remote}\\s+users:\\(\\("{name}",(?:pid=)?{pid},(?:fd=)?[0-9]+\\)\\)$', + Resolver.SS: '^{protocol}\\s+ESTAB\\s+.*\\s+{local}\\s+{remote}\\s+users:\\(\\("{name}",(?:pid=)?{pid},(?:fd=)?[0-9]+\\)\\)\\s*$', # tor 3873 atagar 45u IPv4 40994 0t0 TCP 10.243.55.20:45724->194.154.227.109:9001 (ESTABLISHED) Resolver.LSOF: '^{name}\\s+{pid}\\s+.*\\s+{protocol}\\s+{local}->{remote} \\(ESTABLISHED\\)$', diff --git a/test/settings.cfg b/test/settings.cfg index e49835ea..b1d26d92 100644 --- a/test/settings.cfg +++ b/test/settings.cfg @@ -188,6 +188,7 @@ pycodestyle.ignore stem/descriptor/__init__.py => E402: import stem.descriptor.s pycodestyle.ignore stem/descriptor/__init__.py => E402: import stem.descriptor.tordnsel pycodestyle.ignore test/unit/util/connection.py => W291: _tor tor 15843 10 pipe 0x0 state: pycodestyle.ignore test/unit/util/connection.py => W291: _tor tor 15843 11 pipe 0x0 state: +pycodestyle.ignore test/unit/util/connection.py => W291: tcp ESTAB # False positives from pyflakes. These are mappings between the path and the # issue. diff --git a/test/unit/util/connection.py b/test/unit/util/connection.py index 575667b4..24020c55 100644 --- a/test/unit/util/connection.py +++ b/test/unit/util/connection.py @@ -64,6 +64,12 @@ tcp ESTAB 0 0 127.0.0.1:22 127.0.0.1:56673 tcp ESTAB 0 0 192.168.0.1:44415 38.229.79.2:443 users:(("tor",15843,9)) """ +SS_WHITESPACE_OUTPUT = """\ +Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port +tcp ESTAB 0 0 192.168.0.1:44092 23.112.135.72:443 users:(("tor",15843,10)) +tcp ESTAB 0 0 192.168.0.1:44415 38.229.79.2:443 users:(("tor",15843,9)) +""" + SS_IPV6_OUTPUT = """\ Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port tcp ESTAB 0 0 5.9.158.75:443 107.170.93.13:56159 users:(("tor",pid=25056,fd=997)) @@ -315,6 +321,19 @@ class TestConnection(unittest.TestCase): call_mock.side_effect = OSError('Unable to call ss') self.assertRaises(OSError, stem.util.connection.get_connections, Resolver.SS, process_pid = 1111) + @patch('stem.util.system.call', Mock(return_value = SS_WHITESPACE_OUTPUT.split('\n'))) + def test_get_connections_by_ss_with_whitespace(self): + """ + On some platforms the 'ss' command pads its lines with trailing whitespace. + """ + + expected = [ + Connection('192.168.0.1', 44092, '23.112.135.72', 443, 'tcp', False), + Connection('192.168.0.1', 44415, '38.229.79.2', 443, 'tcp', False), + ] + + self.assertEqual(expected, stem.util.connection.get_connections(Resolver.SS, process_pid = 15843, process_name = 'tor')) + @patch('stem.util.system.call', Mock(return_value = SS_IPV6_OUTPUT.split('\n'))) def test_get_connections_by_ss_ipv6(self): """
participants (1)
-
atagar@torproject.org