[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r19380: {torctl} Add RateLimitedRestriction. Make the NodeRestrictionList be (torctl/trunk/python/TorCtl)



Author: mikeperry
Date: 2009-04-26 23:05:34 -0400 (Sun, 26 Apr 2009)
New Revision: 19380

Modified:
   torctl/trunk/python/TorCtl/PathSupport.py
   torctl/trunk/python/TorCtl/TorCtl.py
Log:

Add RateLimitedRestriction. Make the NodeRestrictionList be
MetaRestriction (and thus pass isinstance(self,
NodeRestriction)). Similar change for PathRestrictionList.



Modified: torctl/trunk/python/TorCtl/PathSupport.py
===================================================================
--- torctl/trunk/python/TorCtl/PathSupport.py	2009-04-26 23:57:26 UTC (rev 19379)
+++ torctl/trunk/python/TorCtl/PathSupport.py	2009-04-27 03:05:34 UTC (rev 19380)
@@ -73,7 +73,7 @@
 "CountryCodeRestriction", "CountryRestriction",
 "UniqueCountryRestriction", "SingleCountryRestriction",
 "ContinentRestriction", "ContinentJumperRestriction",
-"UniqueContinentRestriction"]
+"UniqueContinentRestriction", "MetaPathRestriction", "RateLimitedRestriction"]
 
 #################### Path Support Interfaces #####################
 
@@ -91,46 +91,19 @@
     "Returns true if Router 'r' is acceptable for this restriction"
     return True  
 
-class NodeRestrictionList:
-  "Class to manage a list of NodeRestrictions"
-  def __init__(self, restrictions):
-    "Constructor. 'restrictions' is a list of NodeRestriction instances"
-    self.restrictions = restrictions
-
-  def r_is_ok(self, r):
-    "Returns true of Router 'r' passes all of the contained restrictions"
-    for rs in self.restrictions:
-      if not rs.r_is_ok(r): return False
-    return True
-
-  def add_restriction(self, restr):
-    "Add a NodeRestriction 'restr' to the list of restrictions"
-    self.restrictions.append(restr)
-
-  # TODO: This does not collapse meta restrictions..
-  def del_restriction(self, RestrictionClass):
-    """Remove all restrictions of type RestrictionClass from the list.
-       Does NOT inspect or collapse MetaNode Restrictions (though 
-       MetaRestrictions can be removed if RestrictionClass is 
-       MetaNodeRestriction)"""
-    self.restrictions = filter(
-        lambda r: not isinstance(r, RestrictionClass),
-          self.restrictions)
-  
-  def clear(self):
-    """ Remove all restrictions """
-    self.restrictions = []
-
-  def __str__(self):
-    return self.__class__.__name__+"("+str(map(str, self.restrictions))+")"
-
 class PathRestriction:
   "Interface for path restriction policies"
   def path_is_ok(self, path):
     "Return true if the list of Routers in path satisfies this restriction"
     return True  
 
-class PathRestrictionList:
+# TODO: Or, Not, N of M
+class MetaPathRestriction(PathRestriction):
+  "MetaPathRestrictions are path restriction aggregators."
+  def add_restriction(self, rstr): raise NotImplemented()
+  def del_restriction(self, RestrictionClass): raise NotImplemented()
+ 
+class PathRestrictionList(MetaPathRestriction):
   """Class to manage a list of PathRestrictions"""
   def __init__(self, restrictions):
     "Constructor. 'restrictions' is a list of PathRestriction instances"
@@ -331,6 +304,15 @@
 
   def __str__(self):
     return self.__class__.__name__+"("+str(self.min_bw)+")"
+
+class RateLimitedRestriction(NodeRestriction):
+  def __init__(self, limited=True):
+    self.limited = limited
+
+  def r_is_ok(self, router): return router.rate_limited == self.limited
+
+  def __str__(self):
+    return self.__class__.__name__+"("+str(self.limited)+")"
    
 class VersionIncludeRestriction(NodeRestriction):
   """Require that the version match one in the list"""
@@ -394,6 +376,7 @@
 class MetaNodeRestriction(NodeRestriction):
   """Interface for a NodeRestriction that is an expression consisting of 
      multiple other NodeRestrictions"""
+  def add_restriction(self, rstr): raise NotImplemented()
   # TODO: these should collapse the restriction and return a new
   # instance for re-insertion (or None)
   def next_rstr(self): raise NotImplemented()
@@ -444,7 +427,40 @@
   def __str__(self):
     return self.__class__.__name__+"("+str(map(str, self.rstrs))+","+str(self.n)+")"
 
+class NodeRestrictionList(MetaNodeRestriction):
+  "Class to manage a list of NodeRestrictions"
+  def __init__(self, restrictions):
+    "Constructor. 'restrictions' is a list of NodeRestriction instances"
+    self.restrictions = restrictions
 
+  def r_is_ok(self, r):
+    "Returns true of Router 'r' passes all of the contained restrictions"
+    for rs in self.restrictions:
+      if not rs.r_is_ok(r): return False
+    return True
+
+  def add_restriction(self, restr):
+    "Add a NodeRestriction 'restr' to the list of restrictions"
+    self.restrictions.append(restr)
+
+  # TODO: This does not collapse meta restrictions..
+  def del_restriction(self, RestrictionClass):
+    """Remove all restrictions of type RestrictionClass from the list.
+       Does NOT inspect or collapse MetaNode Restrictions (though 
+       MetaRestrictions can be removed if RestrictionClass is 
+       MetaNodeRestriction)"""
+    self.restrictions = filter(
+        lambda r: not isinstance(r, RestrictionClass),
+          self.restrictions)
+  
+  def clear(self):
+    """ Remove all restrictions """
+    self.restrictions = []
+
+  def __str__(self):
+    return self.__class__.__name__+"("+str(map(str, self.restrictions))+")"
+
+
 #################### Path Restrictions #####################
 
 class Subnet16Restriction(PathRestriction):
@@ -897,10 +913,16 @@
     manager, you must schedule a config update job using 
     PathBuilder.schedule_selmgr() with a worker function to modify 
     this object.
+ 
+    XXX: Warning. The constructor of this class is subject to change
+    and may undergo reorganization in the near future. Watch for falling 
+    bits.
     """
+  # XXX: Hrmm, consider simplifying this. It is confusing and unweildy.
   def __init__(self, pathlen, order_exits,
          percent_fast, percent_skip, min_bw, use_all_exits,
-         uniform, use_exit, use_guards,geoip_config=None,restrict_guards=False):
+         uniform, use_exit, use_guards,geoip_config=None,
+         restrict_guards=False, extra_node_rstr=None):
     BaseSelectionManager.__init__(self)
     self.__ordered_exit_gen = None 
     self.pathlen = pathlen
@@ -916,6 +938,7 @@
     self.restrict_guards_only = restrict_guards
     self.bad_restrictions = False
     self.consensus = None
+    self.extra_node_rstr=extra_node_rstr
 
   def reconfigure(self, consensus=None):
     try:
@@ -977,6 +1000,10 @@
         [PercentileRestriction(nonentry_skip, nonentry_fast, sorted_r),
          FlagsRestriction(["Valid", "Running","Fast"], ["BadExit"])])
 
+    if self.extra_node_rstr:
+      entry_rstr.add_restriction(self.extra_node_rstr)
+      mid_rstr.add_restriction(self.extra_node_rstr)
+      self.exit_rstr.add_restriction(self.extra_node_rstr)
 
     # GeoIP configuration
     if self.geoip_config:
@@ -1147,7 +1174,7 @@
     # sometimes circuit closed events come before the stream
     # close and we need to track those failures..
     self.carried_streams = []
- 
+
   def id_path(self):
     "Returns a list of idhex keys for the path of Routers"
     return map(lambda r: r.idhex, self.path)
@@ -1413,7 +1440,7 @@
     if s.strm_id in self.streams and self.streams[s.strm_id].ignored:
       plog("DEBUG", "Ignoring stream: " + str(s.strm_id))
       return
-  
+
     # XXX: Copy s.circ_id==0 check+reset from StatsSupport here too?
 
     if s.status == "NEW" or s.status == "NEWRESOLVE":

Modified: torctl/trunk/python/TorCtl/TorCtl.py
===================================================================
--- torctl/trunk/python/TorCtl/TorCtl.py	2009-04-26 23:57:26 UTC (rev 19379)
+++ torctl/trunk/python/TorCtl/TorCtl.py	2009-04-27 03:05:34 UTC (rev 19380)
@@ -265,7 +265,7 @@
         self.__dict__[i] =  copy.deepcopy(args[0].__dict__[i])
       return
     else:
-      (idhex, name, bw, down, exitpolicy, flags, ip, version, os, uptime, published, contact) = args
+      (idhex, name, bw, down, exitpolicy, flags, ip, version, os, uptime, published, contact, rate_limited) = args
     self.idhex = idhex
     self.nickname = name
     self.bw = bw
@@ -282,6 +282,7 @@
     self.refcount = 0 # How many open circs are we currently in?
     self.deleted = False # Has Tor already deleted this descriptor?
     self.contact = contact
+    self.rate_limited = rate_limited
 
   def __str__(self):
     s = self.idhex, self.nickname
@@ -328,7 +329,11 @@
       elif rj:
         exitpolicy.append(ExitPolicyLine(False, *rj.groups()))
       elif bw:
-        bw_observed = min(map(int, bw.groups()))
+        bws = map(int, bw.groups())
+        bw_observed = min(bws)
+        rate_limited = False
+        if bws[0] < bws[1]:
+          rate_limited = True
       elif pl:
         version, os = pl.groups()
       elif up:
@@ -348,7 +353,7 @@
     if not version or not os:
       plog("INFO", "No version and/or OS for router " + ns.nickname)
     return Router(ns.idhex, ns.nickname, bw_observed, dead, exitpolicy,
-        ns.flags, ip, version, os, uptime, published, contact)
+        ns.flags, ip, version, os, uptime, published, contact, rate_limited)
   build_from_desc = Callable(build_from_desc)
 
   def update_to(self, new):