diff --git a/nyx/panel/connection.py b/nyx/panel/connection.py index cda75a5..3163b5d 100644 --- a/nyx/panel/connection.py +++ b/nyx/panel/connection.py @@ -433,32 +433,11 @@ def draw(self, subwindow): for line_number in range(scroll, len(lines)): y = line_number + details_offset + 1 - scroll - self._draw_line(subwindow, scroll_offset, y, lines[line_number], lines[line_number] == selected, subwindow.width - scroll_offset, current_time) + _draw_line(subwindow, scroll_offset, y, lines[line_number], lines[line_number] == selected, subwindow.width - scroll_offset, current_time) if y >= subwindow.height: break - def _draw_line(self, subwindow, x, y, line, is_selected, width, current_time): - attr = [CONFIG['attr.connection.category_color'].get(line.entry.get_type(), WHITE)] - attr.append(HIGHLIGHT if is_selected else NORMAL) - - subwindow.addstr(x, y, ' ' * (width - x), *attr) - - if line.line_type == LineType.CIRCUIT: - if line.circuit.path[-1][0] == line.fingerprint: - prefix = (ord(' '), curses.ACS_LLCORNER, curses.ACS_HLINE, ord(' ')) - else: - prefix = (ord(' '), curses.ACS_VLINE, ord(' '), ord(' ')) - - for char in prefix: - x = subwindow._addch(x, y, char) - else: - x += 1 # offset from edge - - _draw_address_column(subwindow, x, y, line, attr) - _draw_line_details(subwindow, 57, y, line, width - 57 - 20, attr) - _draw_right_column(subwindow, width - 18, y, line, current_time, attr) - def _update(self): """ Fetches the newest resolved connections. @@ -532,6 +511,28 @@ def _draw_title(subwindow, entries, showing_details): subwindow.addstr(0, 0, 'Connections (%s):' % ', '.join(count_labels), HIGHLIGHT) +def _draw_line(subwindow, x, y, line, is_selected, width, current_time): + attr = [CONFIG['attr.connection.category_color'].get(line.entry.get_type(), WHITE)] + attr.append(HIGHLIGHT if is_selected else NORMAL) + + subwindow.addstr(x, y, ' ' * (width - x), *attr) + + if line.line_type == LineType.CIRCUIT: + if line.circuit.path[-1][0] == line.fingerprint: + prefix = (ord(' '), curses.ACS_LLCORNER, curses.ACS_HLINE, ord(' ')) + else: + prefix = (ord(' '), curses.ACS_VLINE, ord(' '), ord(' ')) + + for char in prefix: + x = subwindow._addch(x, y, char) + else: + x += 1 # offset from edge + + _draw_address_column(subwindow, x, y, line, attr) + _draw_line_details(subwindow, 57, y, line, width - 57 - 20, attr) + _draw_right_column(subwindow, width - 18, y, line, current_time, attr) + + def _draw_address_column(subwindow, x, y, line, attr): src = tor_controller().get_info('address', line.connection.local_address) src += ':%s' % line.connection.local_port if line.line_type == LineType.CONNECTION else '' diff --git a/test/panel/connection.py b/test/panel/connection.py index 99c185b..632ced0 100644 --- a/test/panel/connection.py +++ b/test/panel/connection.py @@ -181,16 +181,47 @@ def test_draw_details_with_multiple_matches(self, consensus_tracker_mock): self.assertEqual(DETAILS_FOR_MULTIPLE_MATCHES, test.render(nyx.panel.connection._draw_details, line()).content) + @require_curses + @patch('nyx.panel.connection.tor_controller') + def test_draw_line(self, tor_controller_mock): + tor_controller_mock().get_info.return_value = '82.121.9.9' + tor_controller_mock().is_geoip_unavailable.return_value = False + + test_data = { + line(): + ' 75.119.206.243:22 (de) --> 82.121.9.9:3531 15.4s (INBOUND)', + line(entry = MockEntry(entry_type = Category.CIRCUIT), line_type = LineType.CIRCUIT_HEADER): + ' 82.121.9.9 --> 75.119.206.243:22 (de) 15.4s (CIRCUIT)', + line(line_type = LineType.CIRCUIT, fingerprint = '1F43EE37A0670301AD9CB555D94AFEC2C89FDE86'): + ' | 82.121.9.9 1 / Guard', + line(line_type = LineType.CIRCUIT, fingerprint = 'B6D83EC2D9E18B0A7A33428F8CFA9C536769E209'): + ' | 82.121.9.9 2 / Middle', + line(line_type = LineType.CIRCUIT, fingerprint = 'E0BD57A11F00041A9789577C53A1B784473669E4'): + ' +- 82.121.9.9 3 / Exit', + } + + for test_line, expected in test_data.items(): + self.assertEqual(expected, test.render(nyx.panel.connection._draw_line, 0, 0, test_line, False, 80, TIMESTAMP + 15.4).content) + @require_curses @patch('nyx.panel.connection.tor_controller') def test_draw_address_column(self, tor_controller_mock): tor_controller_mock().get_info.return_value = '82.121.9.9' tor_controller_mock().is_geoip_unavailable.return_value = False - self.assertEqual('75.119.206.243:22 (de) --> 82.121.9.9:3531', test.render(nyx.panel.connection._draw_address_column, 0, 0, line(), ()).content) - self.assertEqual('82.121.9.9:3531 --> 75.119.206.243:22 (SSH)', test.render(nyx.panel.connection._draw_address_column, 0, 0, line(entry = MockEntry(entry_type = Category.EXIT)), ()).content) - self.assertEqual('Building... --> 82.121.9.9', test.render(nyx.panel.connection._draw_address_column, 0, 0, line(line_type = LineType.CIRCUIT_HEADER, circ = MockCircuit(status = 'EXTENDING')), ()).content) - self.assertEqual('82.121.9.9', test.render(nyx.panel.connection._draw_address_column, 0, 0, line(line_type = LineType.CIRCUIT), ()).content) + test_data = { + line(): + '75.119.206.243:22 (de) --> 82.121.9.9:3531', + line(entry = MockEntry(entry_type = Category.EXIT)): + '82.121.9.9:3531 --> 75.119.206.243:22 (SSH)', + line(line_type = LineType.CIRCUIT_HEADER, circ = MockCircuit(status = 'EXTENDING')): + 'Building... --> 82.121.9.9', + line(line_type = LineType.CIRCUIT): + '82.121.9.9', + } + + for test_line, expected in test_data.items(): + self.assertEqual(expected, test.render(nyx.panel.connection._draw_address_column, 0, 0, test_line, ()).content) @require_curses @patch('nyx.tracker.get_port_usage_tracker') @@ -201,10 +232,17 @@ def test_draw_line_details(self, port_usage_tracker_mock): port_usage_tracker_mock().fetch.return_value = process - self.assertEqual('1F43EE37A0670301AD9CB555D94AFEC2C89FDE86 Unnamed', test.render(nyx.panel.connection._draw_line_details, 0, 0, line(), 80, ()).content) - self.assertEqual('1F43EE37A0670301AD9CB555D94AFEC2C89FDE86', test.render(nyx.panel.connection._draw_line_details, 0, 0, line(), 45, ()).content) - self.assertEqual('Purpose: General, Circuit ID: 7', test.render(nyx.panel.connection._draw_line_details, 0, 0, line(line_type = LineType.CIRCUIT_HEADER), 45, ()).content) - self.assertEqual('firefox (722)', test.render(nyx.panel.connection._draw_line_details, 0, 0, line(entry = MockEntry(entry_type = Category.CONTROL)), 80, ()).content) + test_data = { + line(): + '1F43EE37A0670301AD9CB555D94AFEC2C89FDE86 Unnamed', + line(line_type = LineType.CIRCUIT_HEADER): + 'Purpose: General, Circuit ID: 7', + line(entry = MockEntry(entry_type = Category.CONTROL)): + 'firefox (722)', + } + + for test_line, expected in test_data.items(): + self.assertEqual(expected, test.render(nyx.panel.connection._draw_line_details, 0, 0, test_line, 80, ()).content) @require_curses def test_draw_right_column(self):