[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [stem/master] Support for CLIENTS_SEEN events
commit 92419a54b83d80d7b124482df9bdf42fb931c7a0
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date: Sun Dec 2 17:23:02 2012 -0800
Support for CLIENTS_SEEN events
Implementation and testing for CLINETS_SEEN events. This would be a difficult
event to get examples for, but luckily the spec has one.
---
stem/control.py | 1 +
stem/response/events.py | 58 ++++++++++++++++++++++++++++++++++++++++++
test/unit/response/events.py | 16 +++++++++++
3 files changed, 75 insertions(+), 0 deletions(-)
diff --git a/stem/control.py b/stem/control.py
index 5fd69c7..ec727ce 100644
--- a/stem/control.py
+++ b/stem/control.py
@@ -82,6 +82,7 @@ providing its own for interacting at a higher level.
**AUTHDIR_NEWDESCS** :class:`stem.response.events.AuthDirNewDescEvent`
**BW** :class:`stem.response.events.BandwidthEvent`
**CIRC** :class:`stem.response.events.CircuitEvent`
+ **CLIENTS_SEEN** :class:`stem.response.events.ClientsSeenEvent`
**DEBUG** :class:`stem.response.events.LogEvent`
**DESCCHANGED** :class:`stem.response.events.DescChangedEvent`
**ERR** :class:`stem.response.events.LogEvent`
diff --git a/stem/response/events.py b/stem/response/events.py
index 1bdfd02..49a8169 100644
--- a/stem/response/events.py
+++ b/stem/response/events.py
@@ -311,6 +311,63 @@ class CircuitEvent(Event):
log_id = "event.circ.unknown_remote_reason.%s" % self.remote_reason
log.log_once(log_id, log.INFO, unrecognized_msg % ('remote reason', self.remote_reason))
+class ClientsSeenEvent(Event):
+ """
+ Periodic event on bridge relays that provides a summary of our users.
+
+ :var datetime start_time: time in UTC that we started collecting these stats
+ :var dict locales: mapping of country codes to a rounded count for the number of users
+ :var dict ip_versions: mapping of ip protocols to a rounded count for the number of users
+ """
+
+ _KEYWORD_ARGS = {
+ "TimeStarted": "start_time",
+ "CountrySummary": "locales",
+ "IPVersions": "ip_versions",
+ }
+
+ _QUOTED = ("TimeStarted",)
+
+ def _parse(self):
+ if self.start_time != None:
+ self.start_time = datetime.datetime.strptime(self.start_time, "%Y-%m-%d %H:%M:%S")
+
+ if self.locales != None:
+ locale_to_count = {}
+
+ for entry in self.locales.split(','):
+ if not '=' in entry:
+ raise stem.ProtocolError("The CLIENTS_SEEN's CountrySummary should be a comma separated listing of '<locale>=<count>' mappings: %s" % self)
+
+ locale, count = entry.split('=', 1)
+
+ if len(locale) != 2:
+ raise stem.ProtocolError("Locales should be a two character code, got '%s': %s" % (locale, self))
+ elif not count.isdigit():
+ raise stem.ProtocolError("Locale count was non-numeric (%s): %s" % (count, self))
+ elif locale in locale_to_count:
+ raise stem.ProtocolError("CountrySummary had multiple mappings for '%s': %s" % (locale, self))
+
+ locale_to_count[locale] = int(count)
+
+ self.locales = locale_to_count
+
+ if self.ip_versions != None:
+ protocol_to_count = {}
+
+ for entry in self.ip_versions.split(','):
+ if not '=' in entry:
+ raise stem.ProtocolError("The CLIENTS_SEEN's IPVersions should be a comma separated listing of '<protocol>=<count>' mappings: %s" % self)
+
+ protocol, count = entry.split('=', 1)
+
+ if not count.isdigit():
+ raise stem.ProtocolError("IP protocol count was non-numeric (%s): %s" % (count, self))
+
+ protocol_to_count[protocol] = int(count)
+
+ self.ip_versions = protocol_to_count
+
class DescChangedEvent(Event):
"""
Event that indicates that our descriptor has changed. This was first added in
@@ -581,6 +638,7 @@ EVENT_TYPE_TO_CLASS = {
"AUTHDIR_NEWDESCS": AuthDirNewDescEvent,
"BW": BandwidthEvent,
"CIRC": CircuitEvent,
+ "CLIENTS_SEEN": ClientsSeenEvent,
"DEBUG": LogEvent,
"DESCCHANGED": DescChangedEvent,
"ERR": LogEvent,
diff --git a/test/unit/response/events.py b/test/unit/response/events.py
index 84a1e7b..0b225d9 100644
--- a/test/unit/response/events.py
+++ b/test/unit/response/events.py
@@ -41,6 +41,13 @@ $E57A476CD4DFBD99B4EE52A100A58610AD6E80B9,hamburgerphone"
CIRC_BUILT_OLD = "650 CIRC 1 BUILT \
$E57A476CD4DFBD99B4EE52A100A58610AD6E80B9,hamburgerphone,PrivacyRepublic14"
+# CLIENTS_SEEN example from the spec
+
+CLIENTS_SEEN_EVENT = '650 CLIENTS_SEEN \
+TimeStarted="2008-12-25 23:50:43" \
+CountrySummary=us=16,de=8,uk=8 \
+IPVersions=v4=16,v6=40'
+
# GUARD events from tor v0.2.1.30.
GUARD_NEW = "650 GUARD ENTRY $36B5DBA788246E8369DBAF58577C6BC044A9A374 NEW"
@@ -343,6 +350,15 @@ class TestEvents(unittest.TestCase):
self.assertEqual(None, event.reason)
self.assertEqual(None, event.remote_reason)
+ def test_clients_seen_event(self):
+ event = _get_event(CLIENTS_SEEN_EVENT)
+
+ self.assertTrue(isinstance(event, stem.response.events.ClientsSeenEvent))
+ self.assertEqual(CLIENTS_SEEN_EVENT.lstrip("650 "), str(event))
+ self.assertEqual(datetime.datetime(2008, 12, 25, 23, 50, 43), event.start_time)
+ self.assertEqual({'us': 16, 'de': 8, 'uk': 8}, event.locales)
+ self.assertEqual({'v4': 16, 'v6': 40}, event.ip_versions)
+
def test_descchanged_event(self):
# all we can check for is that the event is properly parsed as a
# DescChangedEvent instance
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits