<commit_before>#!/usr/bin/python
# This is distributed under cc0. See the LICENCE file distributed along with
# this code.

import random

from py3hax import *
import simtime

class GivingUp(Exception):
    pass

class ExponentialTimer:
    """ Implements an exponential timer using simulated time. """
    def __init__(self, initial, multiplier):
        """Create a timer that's ready to fire immediately.  After
           it first fires, it won't be ready again until 'initial'
           seconds have passed.  Each time after that, it will
           increase the delay by a factor of 'multiplier'.
        """
        self._initial_delay = initial
        self._multiplier = multiplier

        self.reset()

    def reset(self):
        """Reset the timer to the state when it was first created."""
        self._next = 0
        self._cur_delay = self._initial_delay

    def isReady(self):
        """Return true iff the timer is ready to fire now."""
        return self._next <= simtime.now()

    def fire(self):
        """Fire the timer."""
        assert self.isReady()
        self._next = simtime.now() + self._cur_delay
        self._cur_delay *= self._multiplier


class ClientParams:
    """
       Represents the configuration parameters of the client algorithm,
       as given in proposals 259 and 241
    """
    def __init__(self,
                 UTOPIC_GUARDS_THRESHOLD=3,
                 DYSTOPIC_GUARDS_THRESHOLD=3,
                 TOO_MANY_GUARDS=100, # XXX too high
                 TOO_RECENTLY=86400,
                 RETRY_DELAY=30,
                 RETRY_MULT=2):

        # number of guards to keep in a guard list (utopic)
        self.UTOPIC_GUARDS_THRESHOLD = UTOPIC_GUARDS_THRESHOLD

        # number of guards to keep in a guard list (dystopic)
        self.DYSTOPIC_GUARDS_THRESHOLD = DYSTOPIC_GUARDS_THRESHOLD

        # prop241: if we have seen this many guards...
        self.TOO_MANY_GUARDS = TOO_MANY_GUARDS
        # ...within this many simulated seconds, then "freak out".
        self.TOO_RECENTLY = TOO_RECENTLY

        # wait this long after retrying guards the first time
        self.RETRY_DELAY = RETRY_DELAY
        # wait this much longer (factor) after the first time.
        self.RETRY_MULT = RETRY_MULT

class Guard:
    """
       Represents what a client knows about a guard.
    """
    def __init__(self, node):
        # tornet.Node instance
        self._node = node

        # True iff we have marked this node as down.
        self._markedDown = False

        # True iff we have marked this node as up.
        self._markedUp = False

        # True iff we've attempted to connect to this node.
        self._tried = False

        # When did we add it (simulated)?
        self._addedAt = simtime.now()

        # True iff the node is listed as a guard in the most recent consensus
        self._listed = True

    def getNode(self):
        """Return the underlying torsim.Node object for this guard."""
        return self._node

    def mark(self, up):
        """Mark this guard as up or down because of a successful/unsuccessful
           connection attempt."""
        self._tried = True
        if up:
            self._markedDown = False
            self._markedUp = True
        else:
            self._markedDown = True
            self._markedUp = False

    def markUnlisted(self):
        """Mark this guard as unlisted because it didn't appear in the
           most recent consensus."""
        self._listed = False

    def markListed(self):
        """Mark this guard as listed because it did appear in the
           most recent consensus."""
        self._listed = True

    def canTry(self):
        """Return true iff we can try to make a connection to this guard."""
        return self._listed and not (self._tried and self._markedDown)

    def isListed(self):
        """Return true iff the guard is listed in the most recent consensus
           we've seen."""
        return self._listed

    def markForRetry(self):
        """Mark this guard as untried, so that we will be willing to try it
           again."""
        # XXXX We never call this unless _all_ the guards in group seem
        # XXXX down.  But maybe we should give early guards in a list
        # XXXX a chance again after a while?
        self._tried = False

    def addedWithin(self, nSec):
        """Return true iff this guard was added within the last 'nSec'
           simulated seconds."""
        return self._addedAt + nSec >= simtime.now()

class Client:
    """
       A stateful client implementation of the guard selection algorithm.
    """
    def __init__(self, network, parameters):

        # a torsim.Network object.
        self._net = network

        # a ClientParams object
        self._p = parameters

        # lists of current guards in the consensus from the dystopic and
        # utopic sets.  each guard is represented here as a torsim.Node.<commit_msg>Change classes in client.py to be new-style for Python2 and Py3K.<commit_after>#!/usr/bin/python
# This is distributed under cc0. See the LICENCE file distributed along with
# this code.

import random

from py3hax import *
import simtime

class GivingUp(Exception):
    pass

class ExponentialTimer(object):
    """ Implements an exponential timer using simulated time. """
    def __init__(self, initial, multiplier):
        """Create a timer that's ready to fire immediately.  After
           it first fires, it won't be ready again until 'initial'
           seconds have passed.  Each time after that, it will
           increase the delay by a factor of 'multiplier'.
        """
        self._initial_delay = initial
        self._multiplier = multiplier

        self.reset()

    def reset(self):
        """Reset the timer to the state when it was first created."""
        self._next = 0
        self._cur_delay = self._initial_delay

    def isReady(self):
        """Return true iff the timer is ready to fire now."""
        return self._next <= simtime.now()

    def fire(self):
        """Fire the timer."""
        assert self.isReady()
        self._next = simtime.now() + self._cur_delay
        self._cur_delay *= self._multiplier


class ClientParams(object):
    """
       Represents the configuration parameters of the client algorithm,
       as given in proposals 259 and 241
    """
    def __init__(self,
                 UTOPIC_GUARDS_THRESHOLD=3,
                 DYSTOPIC_GUARDS_THRESHOLD=3,
                 TOO_MANY_GUARDS=100, # XXX too high
                 TOO_RECENTLY=86400,
                 RETRY_DELAY=30,
                 RETRY_MULT=2):

        # number of guards to keep in a guard list (utopic)
        self.UTOPIC_GUARDS_THRESHOLD = UTOPIC_GUARDS_THRESHOLD

        # number of guards to keep in a guard list (dystopic)
        self.DYSTOPIC_GUARDS_THRESHOLD = DYSTOPIC_GUARDS_THRESHOLD

        # prop241: if we have seen this many guards...
        self.TOO_MANY_GUARDS = TOO_MANY_GUARDS
        # ...within this many simulated seconds, then "freak out".
        self.TOO_RECENTLY = TOO_RECENTLY

        # wait this long after retrying guards the first time
        self.RETRY_DELAY = RETRY_DELAY
        # wait this much longer (factor) after the first time.
        self.RETRY_MULT = RETRY_MULT

class Guard(object):
    """
       Represents what a client knows about a guard.
    """
    def __init__(self, node):
        # tornet.Node instance
        self._node = node

        # True iff we have marked this node as down.
        self._markedDown = False

        # True iff we have marked this node as up.
        self._markedUp = False

        # True iff we've attempted to connect to this node.
        self._tried = False

        # When did we add it (simulated)?
        self._addedAt = simtime.now()

        # True iff the node is listed as a guard in the most recent consensus
        self._listed = True

    def getNode(self):
        """Return the underlying torsim.Node object for this guard."""
        return self._node

    def mark(self, up):
        """Mark this guard as up or down because of a successful/unsuccessful
           connection attempt."""
        self._tried = True
        if up:
            self._markedDown = False
            self._markedUp = True
        else:
            self._markedDown = True
            self._markedUp = False

    def markUnlisted(self):
        """Mark this guard as unlisted because it didn't appear in the
           most recent consensus."""
        self._listed = False

    def markListed(self):
        """Mark this guard as listed because it did appear in the
           most recent consensus."""
        self._listed = True

    def canTry(self):
        """Return true iff we can try to make a connection to this guard."""
        return self._listed and not (self._tried and self._markedDown)

    def isListed(self):
        """Return true iff the guard is listed in the most recent consensus
           we've seen."""
        return self._listed

    def markForRetry(self):
        """Mark this guard as untried, so that we will be willing to try it
           again."""
        # XXXX We never call this unless _all_ the guards in group seem
        # XXXX down.  But maybe we should give early guards in a list
        # XXXX a chance again after a while?
        self._tried = False

    def addedWithin(self, nSec):
        """Return true iff this guard was added within the last 'nSec'
           simulated seconds."""
        return self._addedAt + nSec >= simtime.now()

class Client(object):
    """
       A stateful client implementation of the guard selection algorithm.
    """
    def __init__(self, network, parameters):

        # a torsim.Network object.
        self._net = network

        # a ClientParams object
        self._p = parameters

        # lists of current guards in the consensus from the dystopic and
        # utopic sets.  each guard is represented here as a torsim.Node.
{'fraction_non_alphanumeric': 0.07331466293258651, 'fraction_numerical': 0.005201040208041608, 'mean_word_length': 2.114953271028037, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4573729', 'n_tokens_mistral': 2809, 'n_tokens_neox': 2664, 'n_words': 1057}