[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [stem/master] Support vote's new bandwidth-file fields
commit 450390e0ce57680d0ae37853b26bec4e90e26d6b
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date: Wed Jun 27 15:57:37 2018 -0700
Support vote's new bandwidth-file fields
Support for a newly added network status vote field...
https://gitweb.torproject.org/torspec.git/commit/?id=84591df
While whipping this up it crossed my mind that the spec is uncommonly loose for
this one. Some examples of odd valid content are...
* Empty lines: 'bandwidth-file'
* Multiple equals: 'bandwidth-file timestamp=12=34'
* Inclusion of these lines in the consensus.
Pointed these out to juga. Also, imho 'headers' should be in the name somewhere
since that's what these are (not a path or file content itself).
---
docs/change_log.rst | 1 +
stem/descriptor/networkstatus.py | 30 ++++++++++++++++++++++-
test/unit/descriptor/networkstatus/document_v3.py | 26 ++++++++++++++++++++
3 files changed, 56 insertions(+), 1 deletion(-)
diff --git a/docs/change_log.rst b/docs/change_log.rst
index e735d6b2..eeaf0362 100644
--- a/docs/change_log.rst
+++ b/docs/change_log.rst
@@ -66,6 +66,7 @@ The following are only available within Stem's `git repository
* `Fallback directory v2 support <https://lists.torproject.org/pipermail/tor-dev/2017-December/012721.html>`_, which adds *nickname* and *extrainfo*
* Added the *orport_v6* attribute to the :class:`~stem.directory.Authority` class
* Added server descriptor's new is_hidden_service_dir attribute
+ * Added the network status vote's new bandwidth_file attribute (:spec:`84591df`)
* Don't retry downloading descriptors when we've timed out
* Don't download from tor26 and Bifroest, which are authorities that frequently timeout
* `stem.descriptor.remote <api/descriptor/remote.html>`_ now consistently defaults **fall_back_to_authority** to false
diff --git a/stem/descriptor/networkstatus.py b/stem/descriptor/networkstatus.py
index 1be802f5..0e1af80b 100644
--- a/stem/descriptor/networkstatus.py
+++ b/stem/descriptor/networkstatus.py
@@ -130,6 +130,7 @@ HEADER_STATUS_DOCUMENT_FIELDS = (
('shared-rand-commit', True, False, False),
('shared-rand-previous-value', True, True, False),
('shared-rand-current-value', True, True, False),
+ ('bandwidth-file', True, False, False),
('recommended-client-protocols', True, True, False),
('recommended-relay-protocols', True, True, False),
('required-client-protocols', True, True, False),
@@ -783,6 +784,27 @@ def _parse_shared_rand_current_value(descriptor, entries):
raise ValueError("A network status document's 'shared-rand-current-value' line must be a pair of values, the first an integer but was '%s'" % value)
+def _parse_bandwidth_file(descriptor, entries):
+ # "bandwidth-file" KeyValues
+ # Value ::= any printing ASCII character except NL and SP.
+ # KeyValue ::= Keyword '=' Value
+ # KeyValues ::= KeyValue | KeyValues SP KeyValue
+
+ value = _value('bandwidth-file', entries)
+ results = {}
+
+ for entry in value.split(' '):
+ if not entry:
+ continue
+ elif '=' not in entry:
+ raise ValueError("'bandwidth-file' lines must be a series of 'key=value' pairs: %s" % value)
+
+ k, v = entry.split('=', 1)
+ results[k] = v
+
+ descriptor.bandwidth_file = results
+
+
_parse_header_valid_after_line = _parse_timestamp_line('valid-after', 'valid_after')
_parse_header_fresh_until_line = _parse_timestamp_line('fresh-until', 'fresh_until')
_parse_header_valid_until_line = _parse_timestamp_line('valid-until', 'valid_until')
@@ -852,6 +874,7 @@ class NetworkStatusDocumentV3(NetworkStatusDocument):
:var dict recommended_relay_protocols: recommended protocols for relays
:var dict required_client_protocols: required protocols for clients
:var dict required_relay_protocols: required protocols for relays
+ :var dict bandwidth_file: bandwidth authority headers that generated this vote
**\*** attribute is either required when we're parsed with validation or has
a default value, others are left as None if undefined
@@ -868,7 +891,7 @@ class NetworkStatusDocumentV3(NetworkStatusDocument):
.. versionchanged:: 1.6.0
Added the recommended_client_protocols, recommended_relay_protocols,
- required_client_protocols, and required_relay_protocols.
+ required_client_protocols, and required_relay_protocols attributes.
.. versionchanged:: 1.6.0
The is_shared_randomness_participate and shared_randomness_commitments
@@ -880,6 +903,9 @@ class NetworkStatusDocumentV3(NetworkStatusDocument):
shared_randomness_previous_reveal_count attributes were undocumented and
not provided properly if retrieved before their shred_randomness_*_value
counterpart.
+
+ .. versionchanged:: 1.7.0
+ Added the bandwidth_file attributbute.
"""
ATTRIBUTES = {
@@ -910,6 +936,7 @@ class NetworkStatusDocumentV3(NetworkStatusDocument):
'shared_randomness_previous_value': (None, _parse_shared_rand_previous_value),
'shared_randomness_current_reveal_count': (None, _parse_shared_rand_current_value),
'shared_randomness_current_value': (None, _parse_shared_rand_current_value),
+ 'bandwidth_file': ({}, _parse_bandwidth_file),
'signatures': ([], _parse_footer_directory_signature_line),
'bandwidth_weights': ({}, _parse_footer_bandwidth_weights_line),
@@ -937,6 +964,7 @@ class NetworkStatusDocumentV3(NetworkStatusDocument):
'params': _parse_header_parameters_line,
'shared-rand-previous-value': _parse_shared_rand_previous_value,
'shared-rand-current-value': _parse_shared_rand_current_value,
+ 'bandwidth-file': _parse_bandwidth_file,
}
FOOTER_PARSER_FOR_LINE = {
diff --git a/test/unit/descriptor/networkstatus/document_v3.py b/test/unit/descriptor/networkstatus/document_v3.py
index 20b38563..6b11fe6c 100644
--- a/test/unit/descriptor/networkstatus/document_v3.py
+++ b/test/unit/descriptor/networkstatus/document_v3.py
@@ -1255,6 +1255,32 @@ DnN5aFtYKiTc19qIC7Nmo+afPdDEf0MlJvEOP5EWl3w=
self.assertEqual(None, authority.shared_randomness_current_reveal_count)
self.assertEqual(None, authority.shared_randomness_current_value)
+ def test_bandwidth_file(self):
+ """
+ Parses a 'bandwidth-file' line of votes.
+ """
+
+ test_values = {
+ '': {},
+ 'timestamp=': {'timestamp': ''},
+ 'timestamp=12=34': {'timestamp': '12=34'},
+ 'timestamp=123': {'timestamp': '123'},
+ 'timestamp=123 version=1.0': {'timestamp': '123', 'version': '1.0'},
+ 'timestamp=123 version=1.0 software=neat_thingy': {'timestamp': '123', 'version': '1.0', 'software': 'neat_thingy'},
+ }
+
+ for test_value, expected_value in test_values.items():
+ document = NetworkStatusDocumentV3.create({'vote-status': 'vote', 'bandwidth-file': test_value})
+ self.assertEqual(expected_value, document.bandwidth_file)
+
+ # there really isn't much that *isn't* valid :P
+
+ content = NetworkStatusDocumentV3.content({'vote-status': 'vote', 'bandwidth-file': 'key_without_value'})
+ self.assertRaises(ValueError, NetworkStatusDocumentV3, content, True)
+
+ document = NetworkStatusDocumentV3(content, False)
+ self.assertEqual(DEFAULT_PARAMS, document.params)
+
def test_with_legacy_directory_authorities(self):
"""
Includes both normal authorities and those following the '-legacy' format.
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits