[tor-commits] [stem/master] Parse bridge-distribution-request in server descriptors

atagar at torproject.org atagar at torproject.org
Tue Oct 10 16:40:03 UTC 2017


commit 3eb59411781c4fa210979cb112b800c001a59f6c
Author: Damian Johnson <atagar at torproject.org>
Date:   Tue Oct 10 09:38:43 2017 -0700

    Parse bridge-distribution-request in server descriptors
    
    Bending my usual policy of only adding parsing support once fields are in the
    spec due to an amusing circular dependency...
    
      https://trac.torproject.org/projects/tor/ticket/21177#comment:5
---
 docs/change_log.rst                       |  1 +
 stem/descriptor/server_descriptor.py      | 35 ++++++++++++++++++++++++++++++-
 test/unit/descriptor/server_descriptor.py | 14 ++++++++++++-
 3 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/docs/change_log.rst b/docs/change_log.rst
index 6e4bcbc6..012b544d 100644
--- a/docs/change_log.rst
+++ b/docs/change_log.rst
@@ -75,6 +75,7 @@ The following are only available within Stem's `git repository
   * Sped descriptor reading by ~25% by deferring defaulting when validating
   * Added server descriptor's new extra_info_sha256_digest attribute (:spec:`0f03581`)
   * Added server descriptor's new protocol attribute (:spec:`eb4fb3c`)
+  * Added server descriptor's new bridge_distribution attribute (:trac:`21177`)
   * Added extrainfo descriptor's new padding_counts attributes (:spec:`0803997`)
   * Shared randomness properties weren't being read in votes (:trac:`21102`)
   * Updated longclaw authority's address (:trac:`23592`)
diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py
index 8489b332..cfb3f710 100644
--- a/stem/descriptor/server_descriptor.py
+++ b/stem/descriptor/server_descriptor.py
@@ -29,6 +29,22 @@ etc). This information is provided from a few sources...
     |- digest - calculates the upper-case hex digest value for our content
     |- get_annotations - dictionary of content prior to the descriptor entry
     +- get_annotation_lines - lines that provided the annotations
+
+.. data:: BridgeDistribution (enum)
+
+  Preferred method of distributing this relay if a bridge.
+
+  .. versionadded:: 1.6.0
+
+  ===================== ===========
+  BridgeDistribution    Description
+  ===================== ===========
+  **ANY**               No proference, BridgeDB will pick how the bridge is distributed.
+  **HTTPS**             Provided via the `web interface <https://bridges.torproject.org>`_.
+  **EMAIL**             Provided in response to emails to bridges at torproject.org.
+  **MOAT**              Provided in interactive menus within Tor Browser.
+  **HYPHAE**            Provided via a cryptographic invitation-based system.
+  ===================== ===========
 """
 
 import base64
@@ -42,6 +58,7 @@ import stem.descriptor.extrainfo_descriptor
 import stem.exit_policy
 import stem.prereq
 import stem.util.connection
+import stem.util.enum
 import stem.util.str_tools
 import stem.util.tor_tools
 import stem.version
@@ -101,6 +118,7 @@ SINGLE_FIELDS = (
   'read-history',
   'write-history',
   'eventdns',
+  'bridge-distribution-request',
   'family',
   'caches-extra-info',
   'extra-info-digest',
@@ -115,8 +133,17 @@ SINGLE_FIELDS = (
   'router-sig-ed25519',
 )
 
+BridgeDistribution = stem.util.enum.Enum(
+  ('ANY', 'any'),
+  ('HTTPS', 'https'),
+  ('EMAIL', 'email'),
+  ('MOAT', 'moat'),
+  ('HYPHAE', 'hyphae'),
+)
+
 DEFAULT_IPV6_EXIT_POLICY = stem.exit_policy.MicroExitPolicy('reject 1-65535')
 REJECT_ALL_POLICY = stem.exit_policy.ExitPolicy('reject *:*')
+DEFAULT_BRIDGE_DISTRIBUTION = 'any'
 
 
 def _truncated_b64encode(content):
@@ -423,6 +450,7 @@ _parse_allow_single_hop_exits_line = _parse_if_present('allow-single-hop-exits',
 _parse_tunneled_dir_server_line = _parse_if_present('tunnelled-dir-server', 'allow_tunneled_dir_requests')
 _parse_proto_line = _parse_protocol_line('proto', 'protocols')
 _parse_caches_extra_info_line = _parse_if_present('caches-extra-info', 'extra_info_cache')
+_parse_bridge_distribution_request_line = _parse_simple_line('bridge-distribution-request', 'bridge_distribution')
 _parse_family_line = _parse_simple_line('family', 'family', func = lambda v: set(v.split(' ')))
 _parse_eventdns_line = _parse_simple_line('eventdns', 'eventdns', func = lambda v: v == '1')
 _parse_onion_key_line = _parse_key_block('onion-key', 'onion_key', 'RSA PUBLIC KEY')
@@ -456,6 +484,8 @@ class ServerDescriptor(Descriptor):
   :var bytes contact: contact information
   :var stem.exit_policy.ExitPolicy exit_policy: **\*** stated exit policy
   :var stem.exit_policy.MicroExitPolicy exit_policy_v6: **\*** exit policy for IPv6
+  :var BridgeDistribution bridge_distribution: **\*** preferred method of providing this relay's
+    address if a bridge
   :var set family: **\*** nicknames or fingerprints of declared family
 
   :var int average_bandwidth: **\*** average rate it's willing to relay in bytes/s
@@ -495,7 +525,8 @@ class ServerDescriptor(Descriptor):
      Added the allow_tunneled_dir_requests attribute.
 
   .. versionchanged:: 1.6.0
-     Added the extra_info_sha256_digest and protocols attributes.
+     Added the extra_info_sha256_digest, protocols, and bridge_distribution
+     attributes.
   """
 
   ATTRIBUTES = {
@@ -515,6 +546,7 @@ class ServerDescriptor(Descriptor):
     'operating_system': (None, _parse_platform_line),
     'uptime': (None, _parse_uptime_line),
     'exit_policy_v6': (DEFAULT_IPV6_EXIT_POLICY, _parse_ipv6_policy_line),
+    'bridge_distribution': (DEFAULT_BRIDGE_DISTRIBUTION, _parse_bridge_distribution_request_line),
     'family': (set(), _parse_family_line),
 
     'average_bandwidth': (None, _parse_bandwidth_line),
@@ -565,6 +597,7 @@ class ServerDescriptor(Descriptor):
     'tunnelled-dir-server': _parse_tunneled_dir_server_line,
     'proto': _parse_proto_line,
     'caches-extra-info': _parse_caches_extra_info_line,
+    'bridge-distribution-request': _parse_bridge_distribution_request_line,
     'family': _parse_family_line,
     'eventdns': _parse_eventdns_line,
   }
diff --git a/test/unit/descriptor/server_descriptor.py b/test/unit/descriptor/server_descriptor.py
index 7bf0b2cf..f392b44f 100644
--- a/test/unit/descriptor/server_descriptor.py
+++ b/test/unit/descriptor/server_descriptor.py
@@ -21,7 +21,7 @@ import test.require
 
 from stem.util import str_type
 from stem.descriptor.certificate import CertType, ExtensionType
-from stem.descriptor.server_descriptor import RelayDescriptor, BridgeDescriptor
+from stem.descriptor.server_descriptor import BridgeDistribution, RelayDescriptor, BridgeDescriptor
 
 from test.unit.descriptor import (
   get_resource,
@@ -141,6 +141,7 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4=
     self.assertEqual('D225B728768D7EA4B5587C13A7A9D22EBBEE6E66', desc.extra_info_digest)
     self.assertEqual(None, desc.extra_info_sha256_digest)
     self.assertEqual(['2'], desc.hidden_service_dir)
+    self.assertEqual(BridgeDistribution.ANY, desc.bridge_distribution)
     self.assertEqual(expected_family, desc.family)
     self.assertEqual(153600, desc.average_bandwidth)
     self.assertEqual(256000, desc.burst_bandwidth)
@@ -200,6 +201,7 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4=
     self.assertEqual(None, desc.extra_info_digest)
     self.assertEqual(None, desc.extra_info_sha256_digest)
     self.assertEqual(None, desc.hidden_service_dir)
+    self.assertEqual(BridgeDistribution.ANY, desc.bridge_distribution)
     self.assertEqual(set(), desc.family)
     self.assertEqual(102400, desc.average_bandwidth)
     self.assertEqual(10485760, desc.burst_bandwidth)
@@ -248,6 +250,7 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4=
     self.assertEqual('56403D838DE152421CD401B8E57DAD4483A3D56B', desc.extra_info_digest)
     self.assertEqual(None, desc.extra_info_sha256_digest)
     self.assertEqual(['2'], desc.hidden_service_dir)
+    self.assertEqual(BridgeDistribution.ANY, desc.bridge_distribution)
     self.assertEqual(set(), desc.family)
     self.assertEqual(102400, desc.average_bandwidth)
     self.assertEqual(204800, desc.burst_bandwidth)
@@ -504,6 +507,7 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4=
     self.assertEqual('BB1F13AA431421BEA29B840A2E33BB1C31C2990B', desc.extra_info_digest)
     self.assertEqual(None, desc.extra_info_sha256_digest)
     self.assertEqual(None, desc.hidden_service_dir)
+    self.assertEqual(BridgeDistribution.ANY, desc.bridge_distribution)
     self.assertEqual(set(), desc.family)
     self.assertEqual(3220480, desc.average_bandwidth)
     self.assertEqual(6441984, desc.burst_bandwidth)
@@ -753,6 +757,14 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4=
     fingerprint = '4F0C 867D F0EF 6816 0568 C826 838F 482C EA7C FE45'
     expect_invalid_attr(self, {'opt fingerprint': fingerprint}, 'fingerprint', fingerprint.replace(' ', ''))
 
+  def test_with_bridge_distribution(self):
+    """
+    Include a preferred method of bridge distribution.
+    """
+
+    desc = RelayDescriptor.create({'bridge-distribution-request': 'email'})
+    self.assertEqual(BridgeDistribution.EMAIL, desc.bridge_distribution)
+
   def test_ipv6_policy(self):
     """
     Checks a 'ipv6-policy' line.



More information about the tor-commits mailing list