[tor-commits] [stem/master] Helper for parsing integer lines

atagar at torproject.org atagar at torproject.org
Sun Aug 25 00:20:44 UTC 2019


commit 546c18a0fc96ab04a7302cd925d1968e10af0a75
Author: Damian Johnson <atagar at torproject.org>
Date:   Sat Aug 24 15:28:33 2019 -0700

    Helper for parsing integer lines
    
    We've done this in quite a few spots, so time for a helper.
---
 stem/descriptor/__init__.py             | 17 +++++++++++++++
 stem/descriptor/extrainfo_descriptor.py | 15 ++-----------
 stem/descriptor/hidden_service.py       | 38 ++++++++-------------------------
 stem/descriptor/server_descriptor.py    | 34 ++++++++++++-----------------
 4 files changed, 42 insertions(+), 62 deletions(-)

diff --git a/stem/descriptor/__init__.py b/stem/descriptor/__init__.py
index 1b5e53bc..3a3d1838 100644
--- a/stem/descriptor/__init__.py
+++ b/stem/descriptor/__init__.py
@@ -657,6 +657,23 @@ def _parse_bytes_line(keyword, attribute):
   return _parse
 
 
+def _parse_int_line(keyword, attribute, allow_negative = True):
+  def _parse(descriptor, entries):
+    value = _value(keyword, entries)
+
+    try:
+      int_val = int(value)
+    except ValueError:
+      raise ValueError('%s must have a numeric value: %s' % (keyword, value))
+
+    if not allow_negative and int_val < 0:
+      raise ValueError('%s must have a positive value: %s' % (keyword, value))
+
+    setattr(descriptor, attribute, int_val)
+
+  return _parse
+
+
 def _parse_timestamp_line(keyword, attribute):
   # "<keyword>" YYYY-MM-DD HH:MM:SS
 
diff --git a/stem/descriptor/extrainfo_descriptor.py b/stem/descriptor/extrainfo_descriptor.py
index 82e3154f..d55b8eef 100644
--- a/stem/descriptor/extrainfo_descriptor.py
+++ b/stem/descriptor/extrainfo_descriptor.py
@@ -88,6 +88,7 @@ from stem.descriptor import (
   _value,
   _values,
   _parse_simple_line,
+  _parse_int_line,
   _parse_timestamp_line,
   _parse_forty_character_hex,
   _parse_key_block,
@@ -306,19 +307,6 @@ def _parse_transport_line(descriptor, entries):
   descriptor.transport = transports
 
 
-def _parse_cell_circuits_per_decline_line(descriptor, entries):
-  # "cell-circuits-per-decile" num
-
-  value = _value('cell-circuits-per-decile', entries)
-
-  if not value.isdigit():
-    raise ValueError('Non-numeric cell-circuits-per-decile value: %s' % value)
-  elif int(value) < 0:
-    raise ValueError('Negative cell-circuits-per-decile value: %s' % value)
-
-  descriptor.cell_circuits_per_decile = int(value)
-
-
 def _parse_padding_counts_line(descriptor, entries):
   # "padding-counts" YYYY-MM-DD HH:MM:SS (NSEC s) key=val key=val...
 
@@ -538,6 +526,7 @@ _parse_dirreq_v3_share_line = functools.partial(_parse_dirreq_share_line, 'dirre
 _parse_cell_processed_cells_line = functools.partial(_parse_cell_line, 'cell-processed-cells', 'cell_processed_cells')
 _parse_cell_queued_cells_line = functools.partial(_parse_cell_line, 'cell-queued-cells', 'cell_queued_cells')
 _parse_cell_time_in_queue_line = functools.partial(_parse_cell_line, 'cell-time-in-queue', 'cell_time_in_queue')
+_parse_cell_circuits_per_decline_line = _parse_int_line('cell-circuits-per-decile', 'cell_circuits_per_decile', allow_negative = False)
 _parse_published_line = _parse_timestamp_line('published', 'published')
 _parse_geoip_start_time_line = _parse_timestamp_line('geoip-start-time', 'geoip_start_time')
 _parse_cell_stats_end_line = functools.partial(_parse_timestamp_and_interval_line, 'cell-stats-end', 'cell_stats_end', 'cell_stats_interval')
diff --git a/stem/descriptor/hidden_service.py b/stem/descriptor/hidden_service.py
index 44bf114b..4af40d46 100644
--- a/stem/descriptor/hidden_service.py
+++ b/stem/descriptor/hidden_service.py
@@ -42,6 +42,7 @@ from stem.descriptor import (
   _bytes_for_block,
   _value,
   _parse_simple_line,
+  _parse_int_line,
   _parse_timestamp_line,
   _parse_key_block,
   _random_date,
@@ -144,31 +145,6 @@ def _parse_file(descriptor_file, desc_type = None, validate = False, **kwargs):
       break  # done parsing file
 
 
-def _parse_version_line(descriptor, entries):
-  if isinstance(descriptor, HiddenServiceDescriptorV2):
-    keyword = 'version'
-  elif isinstance(descriptor, HiddenServiceDescriptorV3):
-    keyword = 'hs-descriptor'
-  else:
-    raise ValueError('BUG: unexpected descriptor type (%s)' % type(descriptor).__name__)
-
-  value = _value(keyword, entries)
-
-  if value.isdigit():
-    descriptor.version = int(value)
-  else:
-    raise ValueError('%s line must have a positive integer value: %s' % (keyword, value))
-
-
-def _parse_lifetime(descriptor, entries):
-  value = _value('descriptor-lifetime', entries)
-
-  if value.isdigit():
-    descriptor.lifetime = int(value)
-  else:
-    raise ValueError('descriptor-lifetime line must have a positive integer value: %s' % value)
-
-
 def _parse_protocol_versions_line(descriptor, entries):
   value = _value('protocol-versions', entries)
 
@@ -199,12 +175,16 @@ def _parse_introduction_points_line(descriptor, entries):
     raise ValueError("'introduction-points' isn't base64 encoded content:\n%s" % block_contents)
 
 
+_parse_v2_version_line = _parse_int_line('version', 'version', allow_negative = False)
 _parse_rendezvous_service_descriptor_line = _parse_simple_line('rendezvous-service-descriptor', 'descriptor_id')
 _parse_permanent_key_line = _parse_key_block('permanent-key', 'permanent_key', 'RSA PUBLIC KEY')
 _parse_secret_id_part_line = _parse_simple_line('secret-id-part', 'secret_id_part')
 _parse_publication_time_line = _parse_timestamp_line('publication-time', 'published')
 _parse_signature_line = _parse_key_block('signature', 'signature', 'SIGNATURE')
 
+_parse_v3_version_line = _parse_int_line('hs-descriptor', 'version', allow_negative = False)
+_parse_lifetime = _parse_int_line('descriptor-lifetime', 'lifetime', allow_negative = False)
+
 
 class BaseHiddenServiceDescriptor(Descriptor):
   """
@@ -252,7 +232,7 @@ class HiddenServiceDescriptorV2(BaseHiddenServiceDescriptor):
 
   ATTRIBUTES = {
     'descriptor_id': (None, _parse_rendezvous_service_descriptor_line),
-    'version': (None, _parse_version_line),
+    'version': (None, _parse_v2_version_line),
     'permanent_key': (None, _parse_permanent_key_line),
     'secret_id_part': (None, _parse_secret_id_part_line),
     'published': (None, _parse_publication_time_line),
@@ -265,7 +245,7 @@ class HiddenServiceDescriptorV2(BaseHiddenServiceDescriptor):
 
   PARSER_FOR_LINE = {
     'rendezvous-service-descriptor': _parse_rendezvous_service_descriptor_line,
-    'version': _parse_version_line,
+    'version': _parse_v2_version_line,
     'permanent-key': _parse_permanent_key_line,
     'secret-id-part': _parse_secret_id_part_line,
     'publication-time': _parse_publication_time_line,
@@ -492,12 +472,12 @@ class HiddenServiceDescriptorV3(BaseHiddenServiceDescriptor):
   TYPE_ANNOTATION_NAME = 'hidden-service-descriptor-3'
 
   ATTRIBUTES = {
-    'version': (None, _parse_version_line),
+    'version': (None, _parse_v3_version_line),
     'lifetime': (None, _parse_lifetime),
   }
 
   PARSER_FOR_LINE = {
-    'hs-descriptor': _parse_version_line,
+    'hs-descriptor': _parse_v3_version_line,
     'descriptor-lifetime': _parse_lifetime,
   }
 
diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py
index 85e35f57..7eaf6e93 100644
--- a/stem/descriptor/server_descriptor.py
+++ b/stem/descriptor/server_descriptor.py
@@ -78,6 +78,7 @@ from stem.descriptor import (
   _value,
   _values,
   _parse_simple_line,
+  _parse_int_line,
   _parse_if_present,
   _parse_bytes_line,
   _parse_timestamp_line,
@@ -337,26 +338,6 @@ def _parse_hibernating_line(descriptor, entries):
   descriptor.hibernating = value == '1'
 
 
-def _parse_uptime_line(descriptor, entries):
-  # We need to be tolerant of negative uptimes to accommodate a past tor
-  # bug...
-  #
-  # Changes in version 0.1.2.7-alpha - 2007-02-06
-  #  - If our system clock jumps back in time, don't publish a negative
-  #    uptime in the descriptor. Also, don't let the global rate limiting
-  #    buckets go absurdly negative.
-  #
-  # After parsing all of the attributes we'll double check that negative
-  # uptimes only occurred prior to this fix.
-
-  value = _value('uptime', entries)
-
-  try:
-    descriptor.uptime = int(value)
-  except ValueError:
-    raise ValueError('Uptime line must have an integer value: %s' % value)
-
-
 def _parse_protocols_line(descriptor, entries):
   value = _value('protocols', entries)
   protocols_match = re.match('^Link (.*) Circuit (.*)$', value)
@@ -454,6 +435,19 @@ _parse_router_sig_ed25519_line = _parse_simple_line('router-sig-ed25519', 'ed255
 _parse_router_digest_sha256_line = _parse_simple_line('router-digest-sha256', 'router_digest_sha256')
 _parse_router_digest_line = _parse_forty_character_hex('router-digest', '_digest')
 
+# TODO: We need to be tolerant of negative uptimes to accommodate a past tor
+# bug...
+#
+# Changes in version 0.1.2.7-alpha - 2007-02-06
+#  - If our system clock jumps back in time, don't publish a negative
+#    uptime in the descriptor. Also, don't let the global rate limiting
+#    buckets go absurdly negative.
+#
+# After parsing all of the attributes we'll double check that negative
+# uptimes only occurred prior to this fix.
+
+_parse_uptime_line = _parse_int_line('uptime', 'uptime', allow_negative = True)
+
 
 class ServerDescriptor(Descriptor):
   """





More information about the tor-commits mailing list