Sophie

Sophie

distrib > Fedora > 18 > i386 > by-pkgid > e4be28b383be195ff28bfce2053e734a > files > 51

python-stem-doc-1.1.0-1.fc18.noarch.rpm



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <title>stem.control &mdash; Stem 1.1.0 documentation</title>
    
    <link rel="stylesheet" href="../../_static/haiku.css" type="text/css" />
    <link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
    <link rel="stylesheet" href="../../_static/print.css" type="text/css" />
    
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '../../',
        VERSION:     '1.1.0',
        COLLAPSE_INDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script>
    <script type="text/javascript" src="../../_static/jquery.js"></script>
    <script type="text/javascript" src="../../_static/underscore.js"></script>
    <script type="text/javascript" src="../../_static/doctools.js"></script>
    <script type="text/javascript" src="../../_static/theme_extras.js"></script>
    <link rel="shortcut icon" href="../../_static/favicon.png"/>
    <link rel="top" title="Stem 1.1.0 documentation" href="../../index.html" />
    <link rel="up" title="stem" href="../stem.html" /> 
  </head>
  <body>
      <div class="header"><img class="rightlogo" src="../../_static/logo.png" alt="Logo"/><h1 class="heading"><a href="../../index.html">
          <span>Stem Docs</span></a></h1>
        <h2 class="heading"><span>stem.control</span></h2>
      </div>
      <div class="topnav">
      
        <p>

        <ul id="navbar">
          <li><a href="../../index.html">Home</a></li>
          <li><a href="../../tutorials.html">Tutorials</a>
            <ul>
              <li><a href="../../tutorials/the_little_relay_that_could.html">Hello World</a></li>
              <li><a href="../../tutorials/to_russia_with_love.html">Client Usage</a></li>
              <li><a href="../../tutorials/tortoise_and_the_hare.html">Event Listening</a></li>
              <li><a href="../../tutorials/mirror_mirror_on_the_wall.html">Tor Descriptors</a></li>
              <li><a href="../../tutorials/east_of_the_sun.html">Utilities</a></li>
              <li><a href="../../tutorials/double_double_toil_and_trouble.html">Examples</a></li>
            </ul>
          </li>
          <li><a href="../../api.html">API</a>
            <ul>
              <li><a href="../../api/control.html">stem.control</a></li>
              <li><a href="../../api/connection.html">stem.connection</a></li>
              <li><a href="../../api/socket.html">stem.socket</a></li>
              <li><a href="../../api/process.html">stem.process</a></li>
              <li><a href="../../api/response.html">stem.response</a></li>
              <li><a href="../../api/exit_policy.html">stem.exit_policy</a></li>
              <li><a href="../../api/version.html">stem.version</a></li>
              <li><a href="../../api.html#descriptors">Descriptors</a></li>
              <li><a href="../../api.html#utilities">Utilities</a></li>
            </ul>
          </li>
          <li><a href="https://trac.torproject.org/projects/tor/wiki/doc/stem">Development</a>
            <ul>
              <li><a href="../../faq.html">FAQ</a></li>
              <li><a href="../../change_log.html">Change Log</a></li>
              <li><a href="https://trac.torproject.org/projects/tor/wiki/doc/stem/bugs">Bug Tracker</a></li>
              <li><a href="../../download.html">Download</a></li>
            </ul>
          </li>
        </ul>
        </p>

      </div>
      <div class="content">
        
        
  <h1>Source code for stem.control</h1><div class="highlight"><pre>
<span class="c"># Copyright 2011-2013, Damian Johnson and The Tor Project</span>
<span class="c"># See LICENSE for licensing information</span>

<span class="sd">&quot;&quot;&quot;</span>
<span class="sd">Classes for interacting with the tor control socket.</span>

<span class="sd">Controllers are a wrapper around a :class:`~stem.socket.ControlSocket`,</span>
<span class="sd">retaining many of its methods (connect, close, is_alive, etc) in addition to</span>
<span class="sd">providing its own for interacting at a higher level.</span>

<span class="sd">**Module Overview:**</span>

<span class="sd">::</span>

<span class="sd">  Controller - General controller class intended for direct use</span>
<span class="sd">    | |- from_port - Provides a Controller based on a port connection.</span>
<span class="sd">    | +- from_socket_file - Provides a Controller based on a socket file connection.</span>
<span class="sd">    |</span>
<span class="sd">    |- authenticate - authenticates this controller with tor</span>
<span class="sd">    |</span>
<span class="sd">    |- get_info - issues a GETINFO query for a parameter</span>
<span class="sd">    |- get_version - provides our tor version</span>
<span class="sd">    |- get_exit_policy - provides our exit policy</span>
<span class="sd">    |- get_socks_listeners - provides where tor is listening for SOCKS connections</span>
<span class="sd">    |- get_protocolinfo - information about the controller interface</span>
<span class="sd">    |- get_user - provides the user tor is running as</span>
<span class="sd">    |- get_pid - provides the pid of our tor process</span>
<span class="sd">    |</span>
<span class="sd">    |- get_microdescriptor - querying the microdescriptor for a relay</span>
<span class="sd">    |- get_microdescriptors - provides all presently available microdescriptors</span>
<span class="sd">    |- get_server_descriptor - querying the server descriptor for a relay</span>
<span class="sd">    |- get_server_descriptors - provides all presently available server descriptors</span>
<span class="sd">    |- get_network_status - querying the router status entry for a relay</span>
<span class="sd">    |- get_network_statuses - provides all preently available router status entries</span>
<span class="sd">    |</span>
<span class="sd">    |- get_conf - gets the value of a configuration option</span>
<span class="sd">    |- get_conf_map - gets the values of multiple configuration options</span>
<span class="sd">    |- set_conf - sets the value of a configuration option</span>
<span class="sd">    |- reset_conf - reverts configuration options to their default values</span>
<span class="sd">    |- set_options - sets or resets the values of multiple configuration options</span>
<span class="sd">    |</span>
<span class="sd">    |- add_event_listener - attaches an event listener to be notified of tor events</span>
<span class="sd">    |- remove_event_listener - removes a listener so it isn&#39;t notified of further events</span>
<span class="sd">    |</span>
<span class="sd">    |- is_caching_enabled - true if the controller has enabled caching</span>
<span class="sd">    |- set_caching - enables or disables caching</span>
<span class="sd">    |- clear_cache - clears any cached results</span>
<span class="sd">    |</span>
<span class="sd">    |- load_conf - loads configuration information as if it was in the torrc</span>
<span class="sd">    |- save_conf - saves configuration information to the torrc</span>
<span class="sd">    |</span>
<span class="sd">    |- is_feature_enabled - checks if a given controller feature is enabled</span>
<span class="sd">    |- enable_feature - enables a controller feature that has been disabled by default</span>
<span class="sd">    |</span>
<span class="sd">    |- get_circuit - provides an active circuit</span>
<span class="sd">    |- get_circuits - provides a list of active circuits</span>
<span class="sd">    |- new_circuit - create new circuits</span>
<span class="sd">    |- extend_circuit - create new circuits and extend existing ones</span>
<span class="sd">    |- repurpose_circuit - change a circuit&#39;s purpose</span>
<span class="sd">    |- close_circuit - close a circuit</span>
<span class="sd">    |</span>
<span class="sd">    |- get_streams - provides a list of active streams</span>
<span class="sd">    |- attach_stream - attach a stream to a circuit</span>
<span class="sd">    |- close_stream - close a stream</span>
<span class="sd">    |</span>
<span class="sd">    |- signal - sends a signal to the tor client</span>
<span class="sd">    |- is_geoip_unavailable - true if we&#39;ve discovered our geoip db to be unavailable</span>
<span class="sd">    +- map_address - maps one address to another such that connections to the original are replaced with the other</span>

<span class="sd">  BaseController - Base controller class asynchronous message handling</span>
<span class="sd">    |- msg - communicates with the tor process</span>
<span class="sd">    |- is_alive - reports if our connection to tor is open or closed</span>
<span class="sd">    |- is_authenticated - checks if we&#39;re authenticated to tor</span>
<span class="sd">    |- connect - connects or reconnects to tor</span>
<span class="sd">    |- close - shuts down our connection to the tor process</span>
<span class="sd">    |- get_socket - provides the socket used for control communication</span>
<span class="sd">    |- get_latest_heartbeat - timestamp for when we last heard from tor</span>
<span class="sd">    |- add_status_listener - notifies a callback of changes in our status</span>
<span class="sd">    |- remove_status_listener - prevents further notification of status changes</span>
<span class="sd">    +- __enter__ / __exit__ - manages socket connection</span>

<span class="sd">.. data:: State (enum)</span>

<span class="sd">  Enumeration for states that a controller can have.</span>

<span class="sd">  ========== ===========</span>
<span class="sd">  State      Description</span>
<span class="sd">  ========== ===========</span>
<span class="sd">  **INIT**   new control connection</span>
<span class="sd">  **RESET**  received a reset/sighup signal</span>
<span class="sd">  **CLOSED** control connection closed</span>
<span class="sd">  ========== ===========</span>

<span class="sd">.. data:: EventType (enum)</span>

<span class="sd">  Known types of events that the</span>
<span class="sd">  :func:`~stem.control.Controller.add_event_listener` method of the</span>
<span class="sd">  :class:`~stem.control.Controller` can listen for.</span>

<span class="sd">  The most frequently listened for event types tend to be the logging events</span>
<span class="sd">  (**DEBUG**, **INFO**, **NOTICE**, **WARN**, and **ERR**), bandwidth usage</span>
<span class="sd">  (**BW**), and circuit or stream changes (**CIRC** and **STREAM**).</span>

<span class="sd">  Enums are mapped to :class:`~stem.response.events.Event` subclasses as</span>
<span class="sd">  follows...</span>

<span class="sd">  ===================== ===========</span>
<span class="sd">  EventType             Event Class</span>
<span class="sd">  ===================== ===========</span>
<span class="sd">  **ADDRMAP**           :class:`stem.response.events.AddrMapEvent`</span>
<span class="sd">  **AUTHDIR_NEWDESCS**  :class:`stem.response.events.AuthDirNewDescEvent`</span>
<span class="sd">  **BUILDTIMEOUT_SET**  :class:`stem.response.events.BuildTimeoutSetEvent`</span>
<span class="sd">  **BW**                :class:`stem.response.events.BandwidthEvent`</span>
<span class="sd">  **CIRC**              :class:`stem.response.events.CircuitEvent`</span>
<span class="sd">  **CIRC_MINOR**        :class:`stem.response.events.CircMinorEvent`</span>
<span class="sd">  **CLIENTS_SEEN**      :class:`stem.response.events.ClientsSeenEvent`</span>
<span class="sd">  **CONF_CHANGED**      :class:`stem.response.events.ConfChangedEvent`</span>
<span class="sd">  **DEBUG**             :class:`stem.response.events.LogEvent`</span>
<span class="sd">  **DESCCHANGED**       :class:`stem.response.events.DescChangedEvent`</span>
<span class="sd">  **ERR**               :class:`stem.response.events.LogEvent`</span>
<span class="sd">  **GUARD**             :class:`stem.response.events.GuardEvent`</span>
<span class="sd">  **INFO**              :class:`stem.response.events.LogEvent`</span>
<span class="sd">  **NEWCONSENSUS**      :class:`stem.response.events.NewConsensusEvent`</span>
<span class="sd">  **NEWDESC**           :class:`stem.response.events.NewDescEvent`</span>
<span class="sd">  **NOTICE**            :class:`stem.response.events.LogEvent`</span>
<span class="sd">  **NS**                :class:`stem.response.events.NetworkStatusEvent`</span>
<span class="sd">  **ORCONN**            :class:`stem.response.events.ORConnEvent`</span>
<span class="sd">  **SIGNAL**            :class:`stem.response.events.SignalEvent`</span>
<span class="sd">  **STATUS_CLIENT**     :class:`stem.response.events.StatusEvent`</span>
<span class="sd">  **STATUS_GENERAL**    :class:`stem.response.events.StatusEvent`</span>
<span class="sd">  **STATUS_SERVER**     :class:`stem.response.events.StatusEvent`</span>
<span class="sd">  **STREAM**            :class:`stem.response.events.StreamEvent`</span>
<span class="sd">  **STREAM_BW**         :class:`stem.response.events.StreamBwEvent`</span>
<span class="sd">  **WARN**              :class:`stem.response.events.LogEvent`</span>
<span class="sd">  ===================== ===========</span>
<span class="sd">&quot;&quot;&quot;</span>

<span class="kn">import</span> <span class="nn">io</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">Queue</span>
<span class="kn">import</span> <span class="nn">StringIO</span>
<span class="kn">import</span> <span class="nn">threading</span>
<span class="kn">import</span> <span class="nn">time</span>

<span class="kn">import</span> <span class="nn">stem.descriptor.microdescriptor</span>
<span class="kn">import</span> <span class="nn">stem.descriptor.reader</span>
<span class="kn">import</span> <span class="nn">stem.descriptor.router_status_entry</span>
<span class="kn">import</span> <span class="nn">stem.descriptor.server_descriptor</span>
<span class="kn">import</span> <span class="nn">stem.exit_policy</span>
<span class="kn">import</span> <span class="nn">stem.response</span>
<span class="kn">import</span> <span class="nn">stem.response.events</span>
<span class="kn">import</span> <span class="nn">stem.socket</span>
<span class="kn">import</span> <span class="nn">stem.util.connection</span>
<span class="kn">import</span> <span class="nn">stem.util.enum</span>
<span class="kn">import</span> <span class="nn">stem.util.str_tools</span>
<span class="kn">import</span> <span class="nn">stem.util.system</span>
<span class="kn">import</span> <span class="nn">stem.util.tor_tools</span>
<span class="kn">import</span> <span class="nn">stem.version</span>

<span class="kn">from</span> <span class="nn">stem</span> <span class="kn">import</span> <span class="n">UNDEFINED</span><span class="p">,</span> <span class="n">CircStatus</span><span class="p">,</span> <span class="n">Signal</span>
<span class="kn">from</span> <span class="nn">stem.util</span> <span class="kn">import</span> <span class="n">log</span>

<span class="c"># state changes a control socket can have</span>

<span class="n">State</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">enum</span><span class="o">.</span><span class="n">Enum</span><span class="p">(</span><span class="s">&quot;INIT&quot;</span><span class="p">,</span> <span class="s">&quot;RESET&quot;</span><span class="p">,</span> <span class="s">&quot;CLOSED&quot;</span><span class="p">)</span>

<span class="n">EventType</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">enum</span><span class="o">.</span><span class="n">UppercaseEnum</span><span class="p">(</span>
  <span class="s">&quot;CIRC&quot;</span><span class="p">,</span>
  <span class="s">&quot;STREAM&quot;</span><span class="p">,</span>
  <span class="s">&quot;ORCONN&quot;</span><span class="p">,</span>
  <span class="s">&quot;BW&quot;</span><span class="p">,</span>
  <span class="s">&quot;DEBUG&quot;</span><span class="p">,</span>
  <span class="s">&quot;INFO&quot;</span><span class="p">,</span>
  <span class="s">&quot;NOTICE&quot;</span><span class="p">,</span>
  <span class="s">&quot;WARN&quot;</span><span class="p">,</span>
  <span class="s">&quot;ERR&quot;</span><span class="p">,</span>
  <span class="s">&quot;NEWDESC&quot;</span><span class="p">,</span>
  <span class="s">&quot;ADDRMAP&quot;</span><span class="p">,</span>
  <span class="s">&quot;AUTHDIR_NEWDESCS&quot;</span><span class="p">,</span>
  <span class="s">&quot;DESCCHANGED&quot;</span><span class="p">,</span>
  <span class="s">&quot;STATUS_GENERAL&quot;</span><span class="p">,</span>
  <span class="s">&quot;STATUS_CLIENT&quot;</span><span class="p">,</span>
  <span class="s">&quot;STATUS_SERVER&quot;</span><span class="p">,</span>
  <span class="s">&quot;GUARD&quot;</span><span class="p">,</span>
  <span class="s">&quot;NS&quot;</span><span class="p">,</span>
  <span class="s">&quot;STREAM_BW&quot;</span><span class="p">,</span>
  <span class="s">&quot;CLIENTS_SEEN&quot;</span><span class="p">,</span>
  <span class="s">&quot;NEWCONSENSUS&quot;</span><span class="p">,</span>
  <span class="s">&quot;BUILDTIMEOUT_SET&quot;</span><span class="p">,</span>
  <span class="s">&quot;SIGNAL&quot;</span><span class="p">,</span>
  <span class="s">&quot;CONF_CHANGED&quot;</span><span class="p">,</span>
  <span class="s">&quot;CIRC_MINOR&quot;</span><span class="p">,</span>
<span class="p">)</span>

<span class="c"># Configuration options that are fetched by a special key. The keys are</span>
<span class="c"># lowercase to make case insensitive lookups easier.</span>

<span class="n">MAPPED_CONFIG_KEYS</span> <span class="o">=</span> <span class="p">{</span>
  <span class="s">&quot;hiddenservicedir&quot;</span><span class="p">:</span> <span class="s">&quot;HiddenServiceOptions&quot;</span><span class="p">,</span>
  <span class="s">&quot;hiddenserviceport&quot;</span><span class="p">:</span> <span class="s">&quot;HiddenServiceOptions&quot;</span><span class="p">,</span>
  <span class="s">&quot;hiddenserviceversion&quot;</span><span class="p">:</span> <span class="s">&quot;HiddenServiceOptions&quot;</span><span class="p">,</span>
  <span class="s">&quot;hiddenserviceauthorizeclient&quot;</span><span class="p">:</span> <span class="s">&quot;HiddenServiceOptions&quot;</span><span class="p">,</span>
  <span class="s">&quot;hiddenserviceoptions&quot;</span><span class="p">:</span> <span class="s">&quot;HiddenServiceOptions&quot;</span>
<span class="p">}</span>

<span class="c"># unchangeable GETINFO parameters</span>

<span class="n">CACHEABLE_GETINFO_PARAMS</span> <span class="o">=</span> <span class="p">(</span>
  <span class="s">&#39;version&#39;</span><span class="p">,</span>
  <span class="s">&#39;config-file&#39;</span><span class="p">,</span>
  <span class="s">&#39;exit-policy/default&#39;</span><span class="p">,</span>
  <span class="s">&#39;fingerprint&#39;</span><span class="p">,</span>
  <span class="s">&#39;config/names&#39;</span><span class="p">,</span>
  <span class="s">&#39;config/defaults&#39;</span><span class="p">,</span>
  <span class="s">&#39;info/names&#39;</span><span class="p">,</span>
  <span class="s">&#39;events/names&#39;</span><span class="p">,</span>
  <span class="s">&#39;features/names&#39;</span><span class="p">,</span>
  <span class="s">&#39;process/descriptor-limit&#39;</span><span class="p">,</span>
<span class="p">)</span>

<span class="c"># GETCONF parameters we shouldn&#39;t cache. This includes hidden service</span>
<span class="c"># perameters due to the funky way they&#39;re set and retrieved (for instance,</span>
<span class="c"># &#39;SETCONF HiddenServiceDir&#39; effects &#39;GETCONF HiddenServiceOptions&#39;).</span>

<span class="n">UNCACHEABLE_GETCONF_PARAMS</span> <span class="o">=</span> <span class="p">(</span>
  <span class="s">&#39;hiddenserviceoptions&#39;</span><span class="p">,</span>
  <span class="s">&#39;hiddenservicedir&#39;</span><span class="p">,</span>
  <span class="s">&#39;hiddenserviceport&#39;</span><span class="p">,</span>
  <span class="s">&#39;hiddenserviceversion&#39;</span><span class="p">,</span>
  <span class="s">&#39;hiddenserviceauthorizeclient&#39;</span><span class="p">,</span>
  <span class="s">&#39;hiddenserviceoptions&#39;</span><span class="p">,</span>
<span class="p">)</span>

<span class="c"># number of sequential attempts before we decide that the Tor geoip database</span>
<span class="c"># is unavailable</span>
<span class="n">GEOIP_FAILURE_THRESHOLD</span> <span class="o">=</span> <span class="mi">5</span>

<span class="n">SERVER_DESCRIPTORS_UNSUPPORTED</span> <span class="o">=</span> <span class="s">&quot;Tor is presently not configured to retrieve </span><span class="se">\</span>
<span class="s">server descriptors. As of Tor version 0.2.3.25 it downloads microdescriptors </span><span class="se">\</span>
<span class="s">instead unless you set &#39;UseMicrodescriptors 0&#39; in your torrc.&quot;</span>


<div class="viewcode-block" id="BaseController"><a class="viewcode-back" href="../../api/control.html#stem.control.BaseController">[docs]</a><span class="k">class</span> <span class="nc">BaseController</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
  <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">  Controller for the tor process. This is a minimal base class for other</span>
<span class="sd">  controllers, providing basic process communication and event listing. Don&#39;t</span>
<span class="sd">  use this directly - subclasses like the :class:`~stem.control.Controller`</span>
<span class="sd">  provide higher level functionality.</span>

<span class="sd">  It&#39;s highly suggested that you don&#39;t interact directly with the</span>
<span class="sd">  :class:`~stem.socket.ControlSocket` that we&#39;re constructed from - use our</span>
<span class="sd">  wrapper methods instead.</span>
<span class="sd">  &quot;&quot;&quot;</span>

  <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">control_socket</span><span class="p">):</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">_socket</span> <span class="o">=</span> <span class="n">control_socket</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">_msg_lock</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">RLock</span><span class="p">()</span>

    <span class="bp">self</span><span class="o">.</span><span class="n">_status_listeners</span> <span class="o">=</span> <span class="p">[]</span>  <span class="c"># tuples of the form (callback, spawn_thread)</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">_status_listeners_lock</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">RLock</span><span class="p">()</span>

    <span class="c"># queues where incoming messages are directed</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">_reply_queue</span> <span class="o">=</span> <span class="n">Queue</span><span class="o">.</span><span class="n">Queue</span><span class="p">()</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">_event_queue</span> <span class="o">=</span> <span class="n">Queue</span><span class="o">.</span><span class="n">Queue</span><span class="p">()</span>

    <span class="c"># thread to continually pull from the control socket</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">_reader_thread</span> <span class="o">=</span> <span class="bp">None</span>

    <span class="c"># thread to pull from the _event_queue and call handle_event</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">_event_notice</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Event</span><span class="p">()</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">_event_thread</span> <span class="o">=</span> <span class="bp">None</span>

    <span class="c"># saves our socket&#39;s prior _connect() and _close() methods so they can be</span>
    <span class="c"># called along with ours</span>

    <span class="bp">self</span><span class="o">.</span><span class="n">_socket_connect</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_socket</span><span class="o">.</span><span class="n">_connect</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">_socket_close</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_socket</span><span class="o">.</span><span class="n">_close</span>

    <span class="bp">self</span><span class="o">.</span><span class="n">_socket</span><span class="o">.</span><span class="n">_connect</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_connect</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">_socket</span><span class="o">.</span><span class="n">_close</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_close</span>

    <span class="bp">self</span><span class="o">.</span><span class="n">_last_heartbeat</span> <span class="o">=</span> <span class="mf">0.0</span>  <span class="c"># timestamp for when we last heard from tor</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">_is_authenticated</span> <span class="o">=</span> <span class="bp">False</span>

    <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_socket</span><span class="o">.</span><span class="n">is_alive</span><span class="p">():</span>
      <span class="bp">self</span><span class="o">.</span><span class="n">_launch_threads</span><span class="p">()</span>

<div class="viewcode-block" id="BaseController.msg"><a class="viewcode-back" href="../../api/control.html#stem.control.BaseController.msg">[docs]</a>  <span class="k">def</span> <span class="nf">msg</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Sends a message to our control socket and provides back its reply.</span>

<span class="sd">    :param str message: message to be formatted and sent to tor</span>

<span class="sd">    :returns: :class:`~stem.response.ControlMessage` with the response</span>

<span class="sd">    :raises:</span>
<span class="sd">      * :class:`stem.ProtocolError` the content from the socket is</span>
<span class="sd">        malformed</span>
<span class="sd">      * :class:`stem.SocketError` if a problem arises in using the</span>
<span class="sd">        socket</span>
<span class="sd">      * :class:`stem.SocketClosed` if the socket is shut down</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">_msg_lock</span><span class="p">:</span>
      <span class="c"># If our _reply_queue isn&#39;t empty then one of a few things happened...</span>
      <span class="c">#</span>
      <span class="c"># - Our connection was closed and probably re-restablished. This was</span>
      <span class="c">#   in reply to pulling for an asynchronous event and getting this is</span>
      <span class="c">#   expected - ignore it.</span>
      <span class="c">#</span>
      <span class="c"># - Pulling for asynchronous events produced an error. If this was a</span>
      <span class="c">#   ProtocolError then it&#39;s a tor bug, and if a non-closure SocketError</span>
      <span class="c">#   then it was probably a socket glitch. Deserves an INFO level log</span>
      <span class="c">#   message.</span>
      <span class="c">#</span>
      <span class="c"># - This is a leftover response for a msg() call. We can&#39;t tell who an</span>
      <span class="c">#   exception was earmarked for, so we only know that this was the case</span>
      <span class="c">#   if it&#39;s a ControlMessage. This should not be possible and indicates</span>
      <span class="c">#   a stem bug. This deserves a NOTICE level log message since it</span>
      <span class="c">#   indicates that one of our callers didn&#39;t get their reply.</span>

      <span class="k">while</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_reply_queue</span><span class="o">.</span><span class="n">empty</span><span class="p">():</span>
        <span class="k">try</span><span class="p">:</span>
          <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_reply_queue</span><span class="o">.</span><span class="n">get_nowait</span><span class="p">()</span>

          <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="n">stem</span><span class="o">.</span><span class="n">SocketClosed</span><span class="p">):</span>
            <span class="k">pass</span>  <span class="c"># this is fine</span>
          <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">):</span>
            <span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s">&quot;Tor provided a malformed message (</span><span class="si">%s</span><span class="s">)&quot;</span> <span class="o">%</span> <span class="n">response</span><span class="p">)</span>
          <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="n">stem</span><span class="o">.</span><span class="n">ControllerError</span><span class="p">):</span>
            <span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s">&quot;Socket experienced a problem (</span><span class="si">%s</span><span class="s">)&quot;</span> <span class="o">%</span> <span class="n">response</span><span class="p">)</span>
          <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="n">stem</span><span class="o">.</span><span class="n">response</span><span class="o">.</span><span class="n">ControlMessage</span><span class="p">):</span>
            <span class="n">log</span><span class="o">.</span><span class="n">notice</span><span class="p">(</span><span class="s">&quot;BUG: the msg() function failed to deliver a response: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">response</span><span class="p">)</span>
        <span class="k">except</span> <span class="n">Queue</span><span class="o">.</span><span class="n">Empty</span><span class="p">:</span>
          <span class="c"># the empty() method is documented to not be fully reliable so this</span>
          <span class="c"># isn&#39;t entirely surprising</span>

          <span class="k">break</span>

      <span class="k">try</span><span class="p">:</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_socket</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
        <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_reply_queue</span><span class="o">.</span><span class="n">get</span><span class="p">()</span>

        <span class="c"># If the message we received back had an exception then re-raise it to the</span>
        <span class="c"># caller. Otherwise return the response.</span>

        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="n">stem</span><span class="o">.</span><span class="n">ControllerError</span><span class="p">):</span>
          <span class="k">raise</span> <span class="n">response</span>
        <span class="k">else</span><span class="p">:</span>
          <span class="c"># I really, really don&#39;t like putting hooks into this method, but</span>
          <span class="c"># this is the most reliable method I can think of for taking actions</span>
          <span class="c"># immediately after successfully authenticating to a connection.</span>

          <span class="k">if</span> <span class="n">message</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&quot;AUTHENTICATE&quot;</span><span class="p">):</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_post_authentication</span><span class="p">()</span>

          <span class="k">return</span> <span class="n">response</span>
      <span class="k">except</span> <span class="n">stem</span><span class="o">.</span><span class="n">SocketClosed</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
        <span class="c"># If the recv() thread caused the SocketClosed then we could still be</span>
        <span class="c"># in the process of closing. Calling close() here so that we can</span>
        <span class="c"># provide an assurance to the caller that when we raise a SocketClosed</span>
        <span class="c"># exception we are shut down afterward for realz.</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
        <span class="k">raise</span> <span class="n">exc</span>
</div>
<div class="viewcode-block" id="BaseController.is_alive"><a class="viewcode-back" href="../../api/control.html#stem.control.BaseController.is_alive">[docs]</a>  <span class="k">def</span> <span class="nf">is_alive</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Checks if our socket is currently connected. This is a pass-through for our</span>
<span class="sd">    socket&#39;s :func:`~stem.socket.ControlSocket.is_alive` method.</span>

<span class="sd">    :returns: **bool** that&#39;s **True** if our socket is connected and **False** otherwise</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_socket</span><span class="o">.</span><span class="n">is_alive</span><span class="p">()</span>
</div>
<div class="viewcode-block" id="BaseController.is_authenticated"><a class="viewcode-back" href="../../api/control.html#stem.control.BaseController.is_authenticated">[docs]</a>  <span class="k">def</span> <span class="nf">is_authenticated</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Checks if our socket is both connected and authenticated.</span>

<span class="sd">    :returns: **bool** that&#39;s **True** if our socket is authenticated to tor</span>
<span class="sd">      and **False** otherwise</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_alive</span><span class="p">():</span>
      <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_is_authenticated</span>

    <span class="k">return</span> <span class="bp">False</span>
</div>
<div class="viewcode-block" id="BaseController.connect"><a class="viewcode-back" href="../../api/control.html#stem.control.BaseController.connect">[docs]</a>  <span class="k">def</span> <span class="nf">connect</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Reconnects our control socket. This is a pass-through for our socket&#39;s</span>
<span class="sd">    :func:`~stem.socket.ControlSocket.connect` method.</span>

<span class="sd">    :raises: :class:`stem.SocketError` if unable to make a socket</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="bp">self</span><span class="o">.</span><span class="n">_socket</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span>
</div>
<div class="viewcode-block" id="BaseController.close"><a class="viewcode-back" href="../../api/control.html#stem.control.BaseController.close">[docs]</a>  <span class="k">def</span> <span class="nf">close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Closes our socket connection. This is a pass-through for our socket&#39;s</span>
<span class="sd">    :func:`~stem.socket.ControlSocket.close` method.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="bp">self</span><span class="o">.</span><span class="n">_socket</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</div>
<div class="viewcode-block" id="BaseController.get_socket"><a class="viewcode-back" href="../../api/control.html#stem.control.BaseController.get_socket">[docs]</a>  <span class="k">def</span> <span class="nf">get_socket</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Provides the socket used to speak with the tor process. Communicating with</span>
<span class="sd">    the socket directly isn&#39;t advised since it may confuse this controller.</span>

<span class="sd">    :returns: :class:`~stem.socket.ControlSocket` we&#39;re communicating with</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_socket</span>
</div>
<div class="viewcode-block" id="BaseController.get_latest_heartbeat"><a class="viewcode-back" href="../../api/control.html#stem.control.BaseController.get_latest_heartbeat">[docs]</a>  <span class="k">def</span> <span class="nf">get_latest_heartbeat</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Provides the unix timestamp for when we last heard from tor. This is zero</span>
<span class="sd">    if we&#39;ve never received a message.</span>

<span class="sd">    :returns: float for the unix timestamp of when we last heard from tor</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_last_heartbeat</span>
</div>
<div class="viewcode-block" id="BaseController.add_status_listener"><a class="viewcode-back" href="../../api/control.html#stem.control.BaseController.add_status_listener">[docs]</a>  <span class="k">def</span> <span class="nf">add_status_listener</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">callback</span><span class="p">,</span> <span class="n">spawn</span> <span class="o">=</span> <span class="bp">True</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Notifies a given function when the state of our socket changes. Functions</span>
<span class="sd">    are expected to be of the form...</span>

<span class="sd">    ::</span>

<span class="sd">      my_function(controller, state, timestamp)</span>

<span class="sd">    The state is a value from the :data:`stem.control.State` enum. Functions</span>
<span class="sd">    **must** allow for new values. The timestamp is a float for the unix time</span>
<span class="sd">    when the change occurred.</span>

<span class="sd">    This class only provides **State.INIT** and **State.CLOSED** notifications.</span>
<span class="sd">    Subclasses may provide others.</span>

<span class="sd">    If spawn is **True** then the callback is notified via a new daemon thread.</span>
<span class="sd">    If **False** then the notice is under our locks, within the thread where</span>
<span class="sd">    the change occurred. In general this isn&#39;t advised, especially if your</span>
<span class="sd">    callback could block for a while.</span>

<span class="sd">    :param function callback: function to be notified when our state changes</span>
<span class="sd">    :param bool spawn: calls function via a new thread if **True**, otherwise</span>
<span class="sd">      it&#39;s part of the connect/close method call</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">_status_listeners_lock</span><span class="p">:</span>
      <span class="bp">self</span><span class="o">.</span><span class="n">_status_listeners</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">callback</span><span class="p">,</span> <span class="n">spawn</span><span class="p">))</span>
</div>
<div class="viewcode-block" id="BaseController.remove_status_listener"><a class="viewcode-back" href="../../api/control.html#stem.control.BaseController.remove_status_listener">[docs]</a>  <span class="k">def</span> <span class="nf">remove_status_listener</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">callback</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Stops listener from being notified of further events.</span>

<span class="sd">    :param function callback: function to be removed from our listeners</span>

<span class="sd">    :returns: **bool** that&#39;s **True** if we removed one or more occurrences of</span>
<span class="sd">      the callback, **False** otherwise</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">_status_listeners_lock</span><span class="p">:</span>
      <span class="n">new_listeners</span><span class="p">,</span> <span class="n">is_changed</span> <span class="o">=</span> <span class="p">[],</span> <span class="bp">False</span>

      <span class="k">for</span> <span class="n">listener</span><span class="p">,</span> <span class="n">spawn</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_status_listeners</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">listener</span> <span class="o">!=</span> <span class="n">callback</span><span class="p">:</span>
          <span class="n">new_listeners</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">listener</span><span class="p">,</span> <span class="n">spawn</span><span class="p">))</span>
        <span class="k">else</span><span class="p">:</span>
          <span class="n">is_changed</span> <span class="o">=</span> <span class="bp">True</span>

      <span class="bp">self</span><span class="o">.</span><span class="n">_status_listeners</span> <span class="o">=</span> <span class="n">new_listeners</span>
      <span class="k">return</span> <span class="n">is_changed</span>
</div>
  <span class="k">def</span> <span class="nf">__enter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="k">return</span> <span class="bp">self</span>

  <span class="k">def</span> <span class="nf">__exit__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exit_type</span><span class="p">,</span> <span class="n">value</span><span class="p">,</span> <span class="n">traceback</span><span class="p">):</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>

  <span class="k">def</span> <span class="nf">_handle_event</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event_message</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Callback to be overwritten by subclasses for event listening. This is</span>
<span class="sd">    notified whenever we receive an event from the control socket.</span>

<span class="sd">    :param stem.response.ControlMessage event_message: message received from</span>
<span class="sd">      the control socket</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">pass</span>

  <span class="k">def</span> <span class="nf">_connect</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">_launch_threads</span><span class="p">()</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">_notify_status_listeners</span><span class="p">(</span><span class="n">State</span><span class="o">.</span><span class="n">INIT</span><span class="p">)</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">_socket_connect</span><span class="p">()</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">_is_authenticated</span> <span class="o">=</span> <span class="bp">False</span>

  <span class="k">def</span> <span class="nf">_close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="c"># Our is_alive() state is now false. Our reader thread should already be</span>
    <span class="c"># awake from recv() raising a closure exception. Wake up the event thread</span>
    <span class="c"># too so it can end.</span>

    <span class="bp">self</span><span class="o">.</span><span class="n">_event_notice</span><span class="o">.</span><span class="n">set</span><span class="p">()</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">_is_authenticated</span> <span class="o">=</span> <span class="bp">False</span>

    <span class="c"># joins on our threads if it&#39;s safe to do so</span>

    <span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_reader_thread</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_event_thread</span><span class="p">):</span>
      <span class="k">if</span> <span class="n">t</span> <span class="ow">and</span> <span class="n">t</span><span class="o">.</span><span class="n">is_alive</span><span class="p">()</span> <span class="ow">and</span> <span class="n">threading</span><span class="o">.</span><span class="n">current_thread</span><span class="p">()</span> <span class="o">!=</span> <span class="n">t</span><span class="p">:</span>
        <span class="n">t</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>

    <span class="bp">self</span><span class="o">.</span><span class="n">_notify_status_listeners</span><span class="p">(</span><span class="n">State</span><span class="o">.</span><span class="n">CLOSED</span><span class="p">)</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">_socket_close</span><span class="p">()</span>

  <span class="k">def</span> <span class="nf">_post_authentication</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="c"># actions to be taken after we have a newly authenticated connection</span>

    <span class="bp">self</span><span class="o">.</span><span class="n">_is_authenticated</span> <span class="o">=</span> <span class="bp">True</span>

  <span class="k">def</span> <span class="nf">_notify_status_listeners</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">state</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Informs our status listeners that a state change occurred.</span>

<span class="sd">    :param stem.control.State state: state change that has occurred</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="c"># Any changes to our is_alive() state happen under the send lock, so we</span>
    <span class="c"># need to have it to ensure it doesn&#39;t change beneath us.</span>

    <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">_socket</span><span class="o">.</span><span class="n">_get_send_lock</span><span class="p">():</span>
      <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">_status_listeners_lock</span><span class="p">:</span>
        <span class="c"># States imply that our socket is either alive or not, which may not</span>
        <span class="c"># hold true when multiple events occur in quick succession. For</span>
        <span class="c"># instance, a sighup could cause two events (State.RESET for the sighup</span>
        <span class="c"># and State.CLOSE if it causes tor to crash). However, there&#39;s no</span>
        <span class="c"># guarantee of the order in which they occur, and it would be bad if</span>
        <span class="c"># listeners got the State.RESET last, implying that we were alive.</span>

        <span class="n">expect_alive</span> <span class="o">=</span> <span class="bp">None</span>

        <span class="k">if</span> <span class="n">state</span> <span class="ow">in</span> <span class="p">(</span><span class="n">State</span><span class="o">.</span><span class="n">INIT</span><span class="p">,</span> <span class="n">State</span><span class="o">.</span><span class="n">RESET</span><span class="p">):</span>
          <span class="n">expect_alive</span> <span class="o">=</span> <span class="bp">True</span>
        <span class="k">elif</span> <span class="n">state</span> <span class="o">==</span> <span class="n">State</span><span class="o">.</span><span class="n">CLOSED</span><span class="p">:</span>
          <span class="n">expect_alive</span> <span class="o">=</span> <span class="bp">False</span>

        <span class="n">change_timestamp</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>

        <span class="k">if</span> <span class="n">expect_alive</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span> <span class="ow">and</span> <span class="n">expect_alive</span> <span class="o">!=</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_alive</span><span class="p">():</span>
          <span class="k">return</span>

        <span class="k">for</span> <span class="n">listener</span><span class="p">,</span> <span class="n">spawn</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_status_listeners</span><span class="p">:</span>
          <span class="k">if</span> <span class="n">spawn</span><span class="p">:</span>
            <span class="n">name</span> <span class="o">=</span> <span class="s">&quot;</span><span class="si">%s</span><span class="s"> notification&quot;</span> <span class="o">%</span> <span class="n">state</span>
            <span class="n">args</span> <span class="o">=</span> <span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">state</span><span class="p">,</span> <span class="n">change_timestamp</span><span class="p">)</span>

            <span class="n">notice_thread</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span> <span class="o">=</span> <span class="n">listener</span><span class="p">,</span> <span class="n">args</span> <span class="o">=</span> <span class="n">args</span><span class="p">,</span> <span class="n">name</span> <span class="o">=</span> <span class="n">name</span><span class="p">)</span>
            <span class="n">notice_thread</span><span class="o">.</span><span class="n">setDaemon</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
            <span class="n">notice_thread</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
          <span class="k">else</span><span class="p">:</span>
            <span class="n">listener</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">state</span><span class="p">,</span> <span class="n">change_timestamp</span><span class="p">)</span>

  <span class="k">def</span> <span class="nf">_launch_threads</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Initializes daemon threads. Threads can&#39;t be reused so we need to recreate</span>
<span class="sd">    them if we&#39;re restarted.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="c"># In theory concurrent calls could result in multiple start() calls on a</span>
    <span class="c"># single thread, which would cause an unexpected exception. Best be safe.</span>

    <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">_socket</span><span class="o">.</span><span class="n">_get_send_lock</span><span class="p">():</span>
      <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_reader_thread</span> <span class="ow">or</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_reader_thread</span><span class="o">.</span><span class="n">is_alive</span><span class="p">():</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_reader_thread</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_reader_loop</span><span class="p">,</span> <span class="n">name</span> <span class="o">=</span> <span class="s">&quot;Tor Listener&quot;</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_reader_thread</span><span class="o">.</span><span class="n">setDaemon</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_reader_thread</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>

      <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_event_thread</span> <span class="ow">or</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_event_thread</span><span class="o">.</span><span class="n">is_alive</span><span class="p">():</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_event_thread</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_event_loop</span><span class="p">,</span> <span class="n">name</span> <span class="o">=</span> <span class="s">&quot;Event Notifier&quot;</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_event_thread</span><span class="o">.</span><span class="n">setDaemon</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_event_thread</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>

  <span class="k">def</span> <span class="nf">_reader_loop</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Continually pulls from the control socket, directing the messages into</span>
<span class="sd">    queues based on their type. Controller messages come in two varieties...</span>

<span class="sd">    * Responses to messages we&#39;ve sent (GETINFO, SETCONF, etc).</span>
<span class="sd">    * Asynchronous events, identified by a status code of 650.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">while</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_alive</span><span class="p">():</span>
      <span class="k">try</span><span class="p">:</span>
        <span class="n">control_message</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_socket</span><span class="o">.</span><span class="n">recv</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_last_heartbeat</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>

        <span class="k">if</span> <span class="n">control_message</span><span class="o">.</span><span class="n">content</span><span class="p">()[</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s">&quot;650&quot;</span><span class="p">:</span>
          <span class="c"># asynchronous message, adds to the event queue and wakes up its handler</span>
          <span class="bp">self</span><span class="o">.</span><span class="n">_event_queue</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="n">control_message</span><span class="p">)</span>
          <span class="bp">self</span><span class="o">.</span><span class="n">_event_notice</span><span class="o">.</span><span class="n">set</span><span class="p">()</span>
        <span class="k">else</span><span class="p">:</span>
          <span class="c"># response to a msg() call</span>
          <span class="bp">self</span><span class="o">.</span><span class="n">_reply_queue</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="n">control_message</span><span class="p">)</span>
      <span class="k">except</span> <span class="n">stem</span><span class="o">.</span><span class="n">ControllerError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
        <span class="c"># Assume that all exceptions belong to the reader. This isn&#39;t always</span>
        <span class="c"># true, but the msg() call can do a better job of sorting it out.</span>
        <span class="c">#</span>
        <span class="c"># Be aware that the msg() method relies on this to unblock callers.</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">_reply_queue</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="n">exc</span><span class="p">)</span>

  <span class="k">def</span> <span class="nf">_event_loop</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Continually pulls messages from the _event_queue and sends them to our</span>
<span class="sd">    handle_event callback. This is done via its own thread so subclasses with a</span>
<span class="sd">    lengthy handle_event implementation don&#39;t block further reading from the</span>
<span class="sd">    socket.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
      <span class="k">try</span><span class="p">:</span>
        <span class="n">event_message</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_event_queue</span><span class="o">.</span><span class="n">get_nowait</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_handle_event</span><span class="p">(</span><span class="n">event_message</span><span class="p">)</span>
      <span class="k">except</span> <span class="n">Queue</span><span class="o">.</span><span class="n">Empty</span><span class="p">:</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_alive</span><span class="p">():</span>
          <span class="k">break</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">_event_notice</span><span class="o">.</span><span class="n">wait</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_event_notice</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span>

</div>
<div class="viewcode-block" id="Controller"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller">[docs]</a><span class="k">class</span> <span class="nc">Controller</span><span class="p">(</span><span class="n">BaseController</span><span class="p">):</span>
  <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">  Communicates with a control socket. This is built on top of the</span>
<span class="sd">  BaseController and provides a more user friendly API for library users.</span>
<span class="sd">  &quot;&quot;&quot;</span>

  <span class="nd">@staticmethod</span>
<div class="viewcode-block" id="Controller.from_port"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.from_port">[docs]</a>  <span class="k">def</span> <span class="nf">from_port</span><span class="p">(</span><span class="n">address</span> <span class="o">=</span> <span class="s">&quot;127.0.0.1&quot;</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="mi">9051</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Constructs a :class:`~stem.socket.ControlPort` based Controller.</span>

<span class="sd">    :param str address: ip address of the controller</span>
<span class="sd">    :param int port: port number of the controller</span>

<span class="sd">    :returns: :class:`~stem.control.Controller` attached to the given port</span>

<span class="sd">    :raises: :class:`stem.SocketError` if we&#39;re unable to establish a connection</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">is_valid_ipv4_address</span><span class="p">(</span><span class="n">address</span><span class="p">):</span>
      <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;Invalid IP address: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">address</span><span class="p">)</span>
    <span class="k">elif</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">is_valid_port</span><span class="p">(</span><span class="n">port</span><span class="p">):</span>
      <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;Invalid port: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">port</span><span class="p">)</span>

    <span class="n">control_port</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">socket</span><span class="o">.</span><span class="n">ControlPort</span><span class="p">(</span><span class="n">address</span><span class="p">,</span> <span class="n">port</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">Controller</span><span class="p">(</span><span class="n">control_port</span><span class="p">)</span>
</div>
  <span class="nd">@staticmethod</span>
<div class="viewcode-block" id="Controller.from_socket_file"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.from_socket_file">[docs]</a>  <span class="k">def</span> <span class="nf">from_socket_file</span><span class="p">(</span><span class="n">path</span> <span class="o">=</span> <span class="s">&quot;/var/run/tor/control&quot;</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Constructs a :class:`~stem.socket.ControlSocketFile` based Controller.</span>

<span class="sd">    :param str path: path where the control socket is located</span>

<span class="sd">    :returns: :class:`~stem.control.Controller` attached to the given socket file</span>

<span class="sd">    :raises: :class:`stem.SocketError` if we&#39;re unable to establish a connection</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="n">control_socket</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">socket</span><span class="o">.</span><span class="n">ControlSocketFile</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">Controller</span><span class="p">(</span><span class="n">control_socket</span><span class="p">)</span>
</div>
  <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">control_socket</span><span class="p">):</span>
    <span class="nb">super</span><span class="p">(</span><span class="n">Controller</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="n">control_socket</span><span class="p">)</span>

    <span class="bp">self</span><span class="o">.</span><span class="n">_is_caching_enabled</span> <span class="o">=</span> <span class="bp">True</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">_request_cache</span> <span class="o">=</span> <span class="p">{}</span>

    <span class="bp">self</span><span class="o">.</span><span class="n">_cache_lock</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">RLock</span><span class="p">()</span>

    <span class="c"># mapping of event types to their listeners</span>

    <span class="bp">self</span><span class="o">.</span><span class="n">_event_listeners</span> <span class="o">=</span> <span class="p">{}</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">_event_listeners_lock</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">RLock</span><span class="p">()</span>

    <span class="c"># number of sequential &#39;GETINFO ip-to-country/*&#39; lookups that have failed</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">_geoip_failure_count</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">_enabled_features</span> <span class="o">=</span> <span class="p">[]</span>

    <span class="k">def</span> <span class="nf">_sighup_listener</span><span class="p">(</span><span class="n">event</span><span class="p">):</span>
      <span class="k">if</span> <span class="n">event</span><span class="o">.</span><span class="n">signal</span> <span class="o">==</span> <span class="n">Signal</span><span class="o">.</span><span class="n">RELOAD</span><span class="p">:</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">clear_cache</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_notify_status_listeners</span><span class="p">(</span><span class="n">State</span><span class="o">.</span><span class="n">RESET</span><span class="p">)</span>

    <span class="bp">self</span><span class="o">.</span><span class="n">add_event_listener</span><span class="p">(</span><span class="n">_sighup_listener</span><span class="p">,</span> <span class="n">EventType</span><span class="o">.</span><span class="n">SIGNAL</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">_confchanged_listener</span><span class="p">(</span><span class="n">event</span><span class="p">):</span>
      <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_caching_enabled</span><span class="p">():</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_set_cache</span><span class="p">(</span><span class="nb">dict</span><span class="p">((</span><span class="n">k</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">event</span><span class="o">.</span><span class="n">config</span><span class="p">),</span> <span class="s">&quot;getconf&quot;</span><span class="p">)</span>

        <span class="k">if</span> <span class="s">&quot;exitpolicy&quot;</span> <span class="ow">in</span> <span class="n">event</span><span class="o">.</span><span class="n">config</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
          <span class="bp">self</span><span class="o">.</span><span class="n">_set_cache</span><span class="p">({</span><span class="s">&quot;exitpolicy&quot;</span><span class="p">:</span> <span class="bp">None</span><span class="p">})</span>

    <span class="bp">self</span><span class="o">.</span><span class="n">add_event_listener</span><span class="p">(</span><span class="n">_confchanged_listener</span><span class="p">,</span> <span class="n">EventType</span><span class="o">.</span><span class="n">CONF_CHANGED</span><span class="p">)</span>

<div class="viewcode-block" id="Controller.connect"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.connect">[docs]</a>  <span class="k">def</span> <span class="nf">connect</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="nb">super</span><span class="p">(</span><span class="n">Controller</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">clear_cache</span><span class="p">()</span>
</div>
<div class="viewcode-block" id="Controller.close"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.close">[docs]</a>  <span class="k">def</span> <span class="nf">close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="c"># making a best-effort attempt to quit before detaching the socket</span>
    <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_alive</span><span class="p">():</span>
      <span class="k">try</span><span class="p">:</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s">&quot;QUIT&quot;</span><span class="p">)</span>
      <span class="k">except</span><span class="p">:</span>
        <span class="k">pass</span>

      <span class="bp">self</span><span class="o">.</span><span class="n">clear_cache</span><span class="p">()</span>

    <span class="nb">super</span><span class="p">(</span><span class="n">Controller</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</div>
<div class="viewcode-block" id="Controller.authenticate"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.authenticate">[docs]</a>  <span class="k">def</span> <span class="nf">authenticate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    A convenience method to authenticate the controller. This is just a</span>
<span class="sd">    pass-through to :func:`stem.connection.authenticate`.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="kn">import</span> <span class="nn">stem.connection</span>
    <span class="n">stem</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">authenticate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="Controller.get_info"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.get_info">[docs]</a>  <span class="k">def</span> <span class="nf">get_info</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">params</span><span class="p">,</span> <span class="n">default</span> <span class="o">=</span> <span class="n">UNDEFINED</span><span class="p">,</span> <span class="n">get_bytes</span> <span class="o">=</span> <span class="bp">False</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Queries the control socket for the given GETINFO option. If provided a</span>
<span class="sd">    default then that&#39;s returned if the GETINFO option is undefined or the</span>
<span class="sd">    call fails for any reason (error response, control port closed, initiated,</span>
<span class="sd">    etc).</span>

<span class="sd">    :param str,list params: GETINFO option or options to be queried</span>
<span class="sd">    :param object default: response if the query fails</span>
<span class="sd">    :param bool get_bytes: provides **bytes** values rather than a **str** under python 3.x</span>

<span class="sd">    :returns:</span>
<span class="sd">      Response depends upon how we were called as follows...</span>

<span class="sd">      * **str** with the response if our param was a **str**</span>
<span class="sd">      * **dict** with the &#39;param =&gt; response&#39; mapping if our param was a **list**</span>
<span class="sd">      * default if one was provided and our call failed</span>

<span class="sd">    :raises:</span>
<span class="sd">      * :class:`stem.ControllerError` if the call fails and we weren&#39;t</span>
<span class="sd">        provided a default response</span>
<span class="sd">      * :class:`stem.InvalidArguments` if the &#39;params&#39; requested was</span>
<span class="sd">        invalid</span>
<span class="sd">      * :class:`stem.ProtocolError` if the geoip database is known to be</span>
<span class="sd">        unavailable</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="n">start_time</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>
    <span class="n">reply</span> <span class="o">=</span> <span class="p">{}</span>

    <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">params</span><span class="p">,</span> <span class="p">(</span><span class="nb">bytes</span><span class="p">,</span> <span class="nb">unicode</span><span class="p">)):</span>
      <span class="n">is_multiple</span> <span class="o">=</span> <span class="bp">False</span>
      <span class="n">params</span> <span class="o">=</span> <span class="nb">set</span><span class="p">([</span><span class="n">params</span><span class="p">])</span>
    <span class="k">else</span><span class="p">:</span>
      <span class="k">if</span> <span class="ow">not</span> <span class="n">params</span><span class="p">:</span>
        <span class="k">return</span> <span class="p">{}</span>

      <span class="n">is_multiple</span> <span class="o">=</span> <span class="bp">True</span>
      <span class="n">params</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span><span class="n">params</span><span class="p">)</span>

    <span class="c"># check for cached results</span>

    <span class="n">from_cache</span> <span class="o">=</span> <span class="p">[</span><span class="n">param</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="k">for</span> <span class="n">param</span> <span class="ow">in</span> <span class="n">params</span><span class="p">]</span>
    <span class="n">cached_results</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_cache_map</span><span class="p">(</span><span class="n">from_cache</span><span class="p">,</span> <span class="s">&quot;getinfo&quot;</span><span class="p">)</span>

    <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">cached_results</span><span class="p">:</span>
      <span class="n">user_expected_key</span> <span class="o">=</span> <span class="n">_case_insensitive_lookup</span><span class="p">(</span><span class="n">params</span><span class="p">,</span> <span class="n">key</span><span class="p">)</span>
      <span class="n">reply</span><span class="p">[</span><span class="n">user_expected_key</span><span class="p">]</span> <span class="o">=</span> <span class="n">cached_results</span><span class="p">[</span><span class="n">key</span><span class="p">]</span>
      <span class="n">params</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">user_expected_key</span><span class="p">)</span>

    <span class="k">for</span> <span class="n">param</span> <span class="ow">in</span> <span class="n">params</span><span class="p">:</span>
      <span class="k">if</span> <span class="n">param</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#39;ip-to-country/&#39;</span><span class="p">)</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_geoip_unavailable</span><span class="p">():</span>
        <span class="c"># the geoip database already looks to be unavailable - abort the request</span>
        <span class="k">if</span> <span class="n">default</span> <span class="o">==</span> <span class="n">UNDEFINED</span><span class="p">:</span>
          <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">(</span><span class="s">&quot;Tor geoip database is unavailable&quot;</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
          <span class="k">return</span> <span class="n">default</span>

    <span class="c"># if everything was cached then short circuit making the query</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">params</span><span class="p">:</span>
      <span class="n">log</span><span class="o">.</span><span class="n">trace</span><span class="p">(</span><span class="s">&quot;GETINFO </span><span class="si">%s</span><span class="s"> (cache fetch)&quot;</span> <span class="o">%</span> <span class="s">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">reply</span><span class="o">.</span><span class="n">keys</span><span class="p">()))</span>

      <span class="k">if</span> <span class="n">is_multiple</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">reply</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">reply</span><span class="o">.</span><span class="n">values</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>

    <span class="k">try</span><span class="p">:</span>
      <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s">&quot;GETINFO </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="s">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">params</span><span class="p">))</span>
      <span class="n">stem</span><span class="o">.</span><span class="n">response</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="s">&quot;GETINFO&quot;</span><span class="p">,</span> <span class="n">response</span><span class="p">)</span>
      <span class="n">response</span><span class="o">.</span><span class="n">_assert_matches</span><span class="p">(</span><span class="n">params</span><span class="p">)</span>

      <span class="c"># usually we want unicode values under python 3.x</span>

      <span class="k">if</span> <span class="n">stem</span><span class="o">.</span><span class="n">prereq</span><span class="o">.</span><span class="n">is_python_3</span><span class="p">()</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">get_bytes</span><span class="p">:</span>
        <span class="n">response</span><span class="o">.</span><span class="n">entries</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">((</span><span class="n">k</span><span class="p">,</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">str_tools</span><span class="o">.</span><span class="n">_to_unicode</span><span class="p">(</span><span class="n">v</span><span class="p">))</span> <span class="k">for</span> <span class="p">(</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span> <span class="ow">in</span> <span class="n">response</span><span class="o">.</span><span class="n">entries</span><span class="o">.</span><span class="n">items</span><span class="p">())</span>

      <span class="n">reply</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">entries</span><span class="p">)</span>

      <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_caching_enabled</span><span class="p">():</span>
        <span class="n">to_cache</span> <span class="o">=</span> <span class="p">{}</span>

        <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">response</span><span class="o">.</span><span class="n">entries</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
          <span class="n">key</span> <span class="o">=</span> <span class="n">key</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>  <span class="c"># make case insensitive</span>

          <span class="k">if</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">CACHEABLE_GETINFO_PARAMS</span><span class="p">:</span>
            <span class="n">to_cache</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
          <span class="k">elif</span> <span class="n">key</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#39;ip-to-country/&#39;</span><span class="p">):</span>
            <span class="c"># both cache-able and means that we should reset the geoip failure count</span>
            <span class="n">to_cache</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_geoip_failure_count</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">_set_cache</span><span class="p">(</span><span class="n">to_cache</span><span class="p">,</span> <span class="s">&quot;getinfo&quot;</span><span class="p">)</span>

      <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&quot;GETINFO </span><span class="si">%s</span><span class="s"> (runtime: </span><span class="si">%0.4f</span><span class="s">)&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="s">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">params</span><span class="p">),</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">start_time</span><span class="p">))</span>

      <span class="k">if</span> <span class="n">is_multiple</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">reply</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">reply</span><span class="o">.</span><span class="n">values</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
    <span class="k">except</span> <span class="n">stem</span><span class="o">.</span><span class="n">ControllerError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
      <span class="c"># bump geoip failure count if...</span>
      <span class="c"># * we&#39;re caching results</span>
      <span class="c"># * this was soley a geoip lookup</span>
      <span class="c"># * we&#39;ve never had a successful geoip lookup (failure count isn&#39;t -1)</span>

      <span class="n">is_geoip_request</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">params</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span> <span class="ow">and</span> <span class="nb">list</span><span class="p">(</span><span class="n">params</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#39;ip-to-country/&#39;</span><span class="p">)</span>

      <span class="k">if</span> <span class="n">is_geoip_request</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_caching_enabled</span><span class="p">()</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">_geoip_failure_count</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_geoip_failure_count</span> <span class="o">+=</span> <span class="mi">1</span>

        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_geoip_unavailable</span><span class="p">():</span>
          <span class="n">log</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s">&quot;Tor&#39;s geoip database is unavailable.&quot;</span><span class="p">)</span>

      <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&quot;GETINFO </span><span class="si">%s</span><span class="s"> (failed: </span><span class="si">%s</span><span class="s">)&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="s">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">params</span><span class="p">),</span> <span class="n">exc</span><span class="p">))</span>

      <span class="k">if</span> <span class="n">default</span> <span class="o">==</span> <span class="n">UNDEFINED</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">exc</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">default</span>
</div>
<div class="viewcode-block" id="Controller.get_version"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.get_version">[docs]</a>  <span class="k">def</span> <span class="nf">get_version</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">default</span> <span class="o">=</span> <span class="n">UNDEFINED</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    A convenience method to get tor version that current controller is</span>
<span class="sd">    connected to.</span>

<span class="sd">    :param object default: response if the query fails</span>

<span class="sd">    :returns: :class:`~stem.version.Version` of the tor instance that we&#39;re</span>
<span class="sd">      connected to</span>

<span class="sd">    :raises:</span>
<span class="sd">      * :class:`stem.ControllerError` if unable to query the version</span>
<span class="sd">      * **ValueError** if unable to parse the version</span>

<span class="sd">      An exception is only raised if we weren&#39;t provided a default response.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">try</span><span class="p">:</span>
      <span class="n">version</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_cache</span><span class="p">(</span><span class="s">&quot;version&quot;</span><span class="p">)</span>

      <span class="k">if</span> <span class="ow">not</span> <span class="n">version</span><span class="p">:</span>
        <span class="n">version</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">version</span><span class="o">.</span><span class="n">Version</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">get_info</span><span class="p">(</span><span class="s">&quot;version&quot;</span><span class="p">))</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_set_cache</span><span class="p">({</span><span class="s">&quot;version&quot;</span><span class="p">:</span> <span class="n">version</span><span class="p">})</span>

      <span class="k">return</span> <span class="n">version</span>
    <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
      <span class="k">if</span> <span class="n">default</span> <span class="o">==</span> <span class="n">UNDEFINED</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">exc</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">default</span>
</div>
<div class="viewcode-block" id="Controller.get_exit_policy"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.get_exit_policy">[docs]</a>  <span class="k">def</span> <span class="nf">get_exit_policy</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">default</span> <span class="o">=</span> <span class="n">UNDEFINED</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Effective ExitPolicy for our relay. This accounts for</span>
<span class="sd">    ExitPolicyRejectPrivate and default policies.</span>

<span class="sd">    :param object default: response if the query fails</span>

<span class="sd">    :returns: :class:`~stem.exit_policy.ExitPolicy` of the tor instance that</span>
<span class="sd">      we&#39;re connected to</span>

<span class="sd">    :raises:</span>
<span class="sd">      * :class:`stem.ControllerError` if unable to query the policy</span>
<span class="sd">      * **ValueError** if unable to parse the policy</span>

<span class="sd">      An exception is only raised if we weren&#39;t provided a default response.</span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">_msg_lock</span><span class="p">:</span>
      <span class="k">try</span><span class="p">:</span>
        <span class="n">config_policy</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_cache</span><span class="p">(</span><span class="s">&quot;exit_policy&quot;</span><span class="p">)</span>

        <span class="k">if</span> <span class="ow">not</span> <span class="n">config_policy</span><span class="p">:</span>
          <span class="n">policy</span> <span class="o">=</span> <span class="p">[]</span>

          <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_conf</span><span class="p">(</span><span class="s">&quot;ExitPolicyRejectPrivate&quot;</span><span class="p">)</span> <span class="o">==</span> <span class="s">&quot;1&quot;</span><span class="p">:</span>
            <span class="n">policy</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&quot;reject private:*&quot;</span><span class="p">)</span>

            <span class="n">public_addr</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_info</span><span class="p">(</span><span class="s">&quot;address&quot;</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>

            <span class="k">if</span> <span class="n">public_addr</span><span class="p">:</span>
              <span class="n">policy</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&quot;reject </span><span class="si">%s</span><span class="s">:*&quot;</span> <span class="o">%</span> <span class="n">public_addr</span><span class="p">)</span>

          <span class="k">for</span> <span class="n">policy_line</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_conf</span><span class="p">(</span><span class="s">&quot;ExitPolicy&quot;</span><span class="p">,</span> <span class="n">multiple</span> <span class="o">=</span> <span class="bp">True</span><span class="p">):</span>
            <span class="n">policy</span> <span class="o">+=</span> <span class="n">policy_line</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&quot;,&quot;</span><span class="p">)</span>

          <span class="n">policy</span> <span class="o">+=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_info</span><span class="p">(</span><span class="s">&quot;exit-policy/default&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&quot;,&quot;</span><span class="p">)</span>

          <span class="n">config_policy</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">exit_policy</span><span class="o">.</span><span class="n">get_config_policy</span><span class="p">(</span><span class="n">policy</span><span class="p">)</span>
          <span class="bp">self</span><span class="o">.</span><span class="n">_set_cache</span><span class="p">({</span><span class="s">&quot;exit_policy&quot;</span><span class="p">:</span> <span class="n">config_policy</span><span class="p">})</span>

        <span class="k">return</span> <span class="n">config_policy</span>
      <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">default</span> <span class="o">==</span> <span class="n">UNDEFINED</span><span class="p">:</span>
          <span class="k">raise</span> <span class="n">exc</span>
        <span class="k">else</span><span class="p">:</span>
          <span class="k">return</span> <span class="n">default</span>
</div>
<div class="viewcode-block" id="Controller.get_socks_listeners"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.get_socks_listeners">[docs]</a>  <span class="k">def</span> <span class="nf">get_socks_listeners</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">default</span> <span class="o">=</span> <span class="n">UNDEFINED</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Provides the SOCKS **(address, port)** tuples that tor has open.</span>

<span class="sd">    :param object default: response if the query fails</span>

<span class="sd">    :returns: list of **(address, port)** tuples for the available SOCKS</span>
<span class="sd">      listeners</span>

<span class="sd">    :raises: :class:`stem.ControllerError` if unable to determine the listeners</span>
<span class="sd">      and no default was provided</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">try</span><span class="p">:</span>
      <span class="n">proxy_addrs</span> <span class="o">=</span> <span class="p">[]</span>

      <span class="k">try</span><span class="p">:</span>
        <span class="k">for</span> <span class="n">listener</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_info</span><span class="p">(</span><span class="s">&quot;net/listeners/socks&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">():</span>
          <span class="k">if</span> <span class="ow">not</span> <span class="p">(</span><span class="n">listener</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#39;&quot;&#39;</span><span class="p">)</span> <span class="ow">and</span> <span class="n">listener</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s">&#39;&quot;&#39;</span><span class="p">)):</span>
            <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">(</span><span class="s">&quot;&#39;GETINFO net/listeners/socks&#39; responses are expected to be quoted: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">listener</span><span class="p">)</span>
          <span class="k">elif</span> <span class="ow">not</span> <span class="s">&#39;:&#39;</span> <span class="ow">in</span> <span class="n">listener</span><span class="p">:</span>
            <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">(</span><span class="s">&quot;&#39;GETINFO net/listeners/socks&#39; had a listener without a colon: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">listener</span><span class="p">)</span>

          <span class="n">listener</span> <span class="o">=</span> <span class="n">listener</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>  <span class="c"># strip quotes</span>
          <span class="n">addr</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="n">listener</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;:&#39;</span><span class="p">)</span>
          <span class="n">proxy_addrs</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">addr</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>
      <span class="k">except</span> <span class="n">stem</span><span class="o">.</span><span class="n">InvalidArguments</span><span class="p">:</span>
        <span class="c"># tor version is old (pre-tor-0.2.2.26-beta), use get_conf() instead</span>
        <span class="n">socks_port</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_conf</span><span class="p">(</span><span class="s">&#39;SocksPort&#39;</span><span class="p">)</span>

        <span class="k">for</span> <span class="n">listener</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_conf</span><span class="p">(</span><span class="s">&#39;SocksListenAddress&#39;</span><span class="p">,</span> <span class="n">multiple</span> <span class="o">=</span> <span class="bp">True</span><span class="p">):</span>
          <span class="k">if</span> <span class="s">&#39;:&#39;</span> <span class="ow">in</span> <span class="n">listener</span><span class="p">:</span>
            <span class="n">addr</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="n">listener</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;:&#39;</span><span class="p">)</span>
            <span class="n">proxy_addrs</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">addr</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>
          <span class="k">else</span><span class="p">:</span>
            <span class="n">proxy_addrs</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">listener</span><span class="p">,</span> <span class="n">socks_port</span><span class="p">))</span>

      <span class="c"># validate that address/ports are valid, and convert ports to ints</span>

      <span class="k">for</span> <span class="n">addr</span><span class="p">,</span> <span class="n">port</span> <span class="ow">in</span> <span class="n">proxy_addrs</span><span class="p">:</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">is_valid_ipv4_address</span><span class="p">(</span><span class="n">addr</span><span class="p">):</span>
          <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">(</span><span class="s">&quot;Invalid address for a SOCKS listener: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">addr</span><span class="p">)</span>
        <span class="k">elif</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">is_valid_port</span><span class="p">(</span><span class="n">port</span><span class="p">):</span>
          <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">(</span><span class="s">&quot;Invalid port for a SOCKS listener: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">port</span><span class="p">)</span>

      <span class="k">return</span> <span class="p">[(</span><span class="n">addr</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">port</span><span class="p">))</span> <span class="k">for</span> <span class="p">(</span><span class="n">addr</span><span class="p">,</span> <span class="n">port</span><span class="p">)</span> <span class="ow">in</span> <span class="n">proxy_addrs</span><span class="p">]</span>
    <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
      <span class="k">if</span> <span class="n">default</span> <span class="o">==</span> <span class="n">UNDEFINED</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">exc</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">default</span>
</div>
<div class="viewcode-block" id="Controller.get_protocolinfo"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.get_protocolinfo">[docs]</a>  <span class="k">def</span> <span class="nf">get_protocolinfo</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">default</span> <span class="o">=</span> <span class="n">UNDEFINED</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    A convenience method to get the protocol info of the controller.</span>

<span class="sd">    :param object default: response if the query fails</span>

<span class="sd">    :returns: :class:`~stem.response.protocolinfo.ProtocolInfoResponse` provided by tor</span>

<span class="sd">    :raises:</span>
<span class="sd">      * :class:`stem.ProtocolError` if the PROTOCOLINFO response is</span>
<span class="sd">        malformed</span>
<span class="sd">      * :class:`stem.SocketError` if problems arise in establishing or</span>
<span class="sd">        using the socket</span>

<span class="sd">      An exception is only raised if we weren&#39;t provided a default response.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="kn">import</span> <span class="nn">stem.connection</span>

    <span class="k">try</span><span class="p">:</span>
      <span class="k">return</span> <span class="n">stem</span><span class="o">.</span><span class="n">connection</span><span class="o">.</span><span class="n">get_protocolinfo</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
    <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
      <span class="k">if</span> <span class="n">default</span> <span class="o">==</span> <span class="n">UNDEFINED</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">exc</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">default</span>
</div>
<div class="viewcode-block" id="Controller.get_user"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.get_user">[docs]</a>  <span class="k">def</span> <span class="nf">get_user</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">default</span> <span class="o">=</span> <span class="n">UNDEFINED</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Provides the user tor is running as. This often only works if tor is</span>
<span class="sd">    running locally. Also, most of its checks are platform dependent, and hence</span>
<span class="sd">    are not entirely reliable.</span>

<span class="sd">    :param object default: response if the query fails</span>

<span class="sd">    :returns: str with the username tor is running as</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="n">user</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_cache</span><span class="p">(</span><span class="s">&quot;user&quot;</span><span class="p">)</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="n">user</span><span class="p">:</span>
      <span class="n">user</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_info</span><span class="p">(</span><span class="s">&quot;process/user&quot;</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="n">user</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_socket</span><span class="p">()</span><span class="o">.</span><span class="n">is_localhost</span><span class="p">():</span>
      <span class="n">pid</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_pid</span><span class="p">(</span><span class="bp">None</span><span class="p">)</span>

      <span class="k">if</span> <span class="n">pid</span><span class="p">:</span>
        <span class="n">user</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">system</span><span class="o">.</span><span class="n">get_user</span><span class="p">(</span><span class="n">pid</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">user</span><span class="p">:</span>
      <span class="bp">self</span><span class="o">.</span><span class="n">_set_cache</span><span class="p">({</span><span class="s">&quot;user&quot;</span><span class="p">:</span> <span class="n">user</span><span class="p">})</span>
      <span class="k">return</span> <span class="n">user</span>
    <span class="k">elif</span> <span class="n">default</span> <span class="o">==</span> <span class="n">UNDEFINED</span><span class="p">:</span>
      <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_socket</span><span class="p">()</span><span class="o">.</span><span class="n">is_localhost</span><span class="p">():</span>
        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;Unable to resolve tor&#39;s user&quot;</span><span class="p">)</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;Tor isn&#39;t running locally&quot;</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
      <span class="k">return</span> <span class="n">default</span>
</div>
<div class="viewcode-block" id="Controller.get_pid"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.get_pid">[docs]</a>  <span class="k">def</span> <span class="nf">get_pid</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">default</span> <span class="o">=</span> <span class="n">UNDEFINED</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Provides the process id of tor. This often only works if tor is running</span>
<span class="sd">    locally. Also, most of its checks are platform dependent, and hence are not</span>
<span class="sd">    entirely reliable.</span>

<span class="sd">    :param object default: response if the query fails</span>

<span class="sd">    :returns: int with our process&#39; pid</span>

<span class="sd">    :raises: **ValueError** if unable to determine the pid and no default was</span>
<span class="sd">      provided</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="n">pid</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_cache</span><span class="p">(</span><span class="s">&quot;pid&quot;</span><span class="p">)</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="n">pid</span><span class="p">:</span>
      <span class="n">getinfo_pid</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_info</span><span class="p">(</span><span class="s">&quot;process/pid&quot;</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>

      <span class="k">if</span> <span class="n">getinfo_pid</span> <span class="ow">and</span> <span class="n">getinfo_pid</span><span class="o">.</span><span class="n">isdigit</span><span class="p">():</span>
        <span class="n">pid</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">getinfo_pid</span><span class="p">)</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="n">pid</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_socket</span><span class="p">()</span><span class="o">.</span><span class="n">is_localhost</span><span class="p">():</span>
      <span class="n">pid_file_path</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_conf</span><span class="p">(</span><span class="s">&quot;PidFile&quot;</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>

      <span class="k">if</span> <span class="n">pid_file_path</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
        <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">pid_file_path</span><span class="p">)</span> <span class="k">as</span> <span class="n">pid_file</span><span class="p">:</span>
          <span class="n">pid_file_contents</span> <span class="o">=</span> <span class="n">pid_file</span><span class="o">.</span><span class="n">read</span><span class="p">()</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>

          <span class="k">if</span> <span class="n">pid_file_contents</span><span class="o">.</span><span class="n">isdigit</span><span class="p">():</span>
            <span class="n">pid</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">pid_file_contents</span><span class="p">)</span>

      <span class="k">if</span> <span class="ow">not</span> <span class="n">pid</span><span class="p">:</span>
        <span class="n">pid</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">system</span><span class="o">.</span><span class="n">get_pid_by_name</span><span class="p">(</span><span class="s">&#39;tor&#39;</span><span class="p">)</span>

      <span class="k">if</span> <span class="ow">not</span> <span class="n">pid</span><span class="p">:</span>
        <span class="n">control_socket</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_socket</span><span class="p">()</span>

        <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">control_socket</span><span class="p">,</span> <span class="n">stem</span><span class="o">.</span><span class="n">socket</span><span class="o">.</span><span class="n">ControlPort</span><span class="p">):</span>
          <span class="n">pid</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">system</span><span class="o">.</span><span class="n">get_pid_by_port</span><span class="p">(</span><span class="n">control_socket</span><span class="o">.</span><span class="n">get_port</span><span class="p">())</span>
        <span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">control_socket</span><span class="p">,</span> <span class="n">stem</span><span class="o">.</span><span class="n">socket</span><span class="o">.</span><span class="n">ControlSocketFile</span><span class="p">):</span>
          <span class="n">pid</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">system</span><span class="o">.</span><span class="n">get_pid_by_open_file</span><span class="p">(</span><span class="n">control_socket</span><span class="o">.</span><span class="n">get_socket_path</span><span class="p">())</span>

    <span class="k">if</span> <span class="n">pid</span><span class="p">:</span>
      <span class="bp">self</span><span class="o">.</span><span class="n">_set_cache</span><span class="p">({</span><span class="s">&quot;pid&quot;</span><span class="p">:</span> <span class="n">pid</span><span class="p">})</span>
      <span class="k">return</span> <span class="n">pid</span>
    <span class="k">elif</span> <span class="n">default</span> <span class="o">==</span> <span class="n">UNDEFINED</span><span class="p">:</span>
      <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_socket</span><span class="p">()</span><span class="o">.</span><span class="n">is_localhost</span><span class="p">():</span>
        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;Unable to resolve tor&#39;s pid&quot;</span><span class="p">)</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;Tor isn&#39;t running locally&quot;</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
      <span class="k">return</span> <span class="n">default</span>
</div>
<div class="viewcode-block" id="Controller.get_microdescriptor"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.get_microdescriptor">[docs]</a>  <span class="k">def</span> <span class="nf">get_microdescriptor</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">relay</span><span class="p">,</span> <span class="n">default</span> <span class="o">=</span> <span class="n">UNDEFINED</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Provides the microdescriptor for the relay with the given fingerprint or</span>
<span class="sd">    nickname. If the relay identifier could be either a fingerprint *or*</span>
<span class="sd">    nickname then it&#39;s queried as a fingerprint.</span>

<span class="sd">    :param str relay: fingerprint or nickname of the relay to be queried</span>
<span class="sd">    :param object default: response if the query fails</span>

<span class="sd">    :returns: :class:`~stem.descriptor.microdescriptor.Microdescriptor` for the given relay</span>

<span class="sd">    :raises:</span>
<span class="sd">      * :class:`stem.ControllerError` if unable to query the descriptor</span>
<span class="sd">      * **ValueError** if **relay** doesn&#39;t conform with the pattern for being</span>
<span class="sd">        a fingerprint or nickname</span>

<span class="sd">      An exception is only raised if we weren&#39;t provided a default response.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">try</span><span class="p">:</span>
      <span class="k">if</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">tor_tools</span><span class="o">.</span><span class="n">is_valid_fingerprint</span><span class="p">(</span><span class="n">relay</span><span class="p">):</span>
        <span class="n">query</span> <span class="o">=</span> <span class="s">&quot;md/id/</span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">relay</span>
      <span class="k">elif</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">tor_tools</span><span class="o">.</span><span class="n">is_valid_nickname</span><span class="p">(</span><span class="n">relay</span><span class="p">):</span>
        <span class="n">query</span> <span class="o">=</span> <span class="s">&quot;md/name/</span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">relay</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;&#39;</span><span class="si">%s</span><span class="s">&#39; isn&#39;t a valid fingerprint or nickname&quot;</span> <span class="o">%</span> <span class="n">relay</span><span class="p">)</span>

      <span class="n">desc_content</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_info</span><span class="p">(</span><span class="n">query</span><span class="p">,</span> <span class="n">get_bytes</span> <span class="o">=</span> <span class="bp">True</span><span class="p">)</span>
      <span class="k">return</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">microdescriptor</span><span class="o">.</span><span class="n">Microdescriptor</span><span class="p">(</span><span class="n">desc_content</span><span class="p">)</span>
    <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
      <span class="k">if</span> <span class="n">default</span> <span class="o">==</span> <span class="n">UNDEFINED</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">exc</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">default</span>
</div>
<div class="viewcode-block" id="Controller.get_microdescriptors"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.get_microdescriptors">[docs]</a>  <span class="k">def</span> <span class="nf">get_microdescriptors</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">default</span> <span class="o">=</span> <span class="n">UNDEFINED</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Provides an iterator for all of the microdescriptors that tor presently</span>
<span class="sd">    knows about.</span>

<span class="sd">    **Tor does not expose this information via the control protocol**</span>
<span class="sd">    (:trac:`8323`). Until it does this reads the microdescriptors from disk,</span>
<span class="sd">    and hence won&#39;t work remotely or if we lack read permissions.</span>

<span class="sd">    :param list default: items to provide if the query fails</span>

<span class="sd">    :returns: iterates over</span>
<span class="sd">      :class:`~stem.descriptor.microdescriptor.Microdescriptor` for relays in</span>
<span class="sd">      the tor network</span>

<span class="sd">    :raises: :class:`stem.ControllerError` if unable to query tor and no</span>
<span class="sd">      default was provided</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">try</span><span class="p">:</span>
      <span class="k">try</span><span class="p">:</span>
        <span class="n">data_directory</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_conf</span><span class="p">(</span><span class="s">&quot;DataDirectory&quot;</span><span class="p">)</span>
      <span class="k">except</span> <span class="n">stem</span><span class="o">.</span><span class="n">ControllerError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">OperationFailed</span><span class="p">(</span><span class="n">message</span> <span class="o">=</span> <span class="s">&quot;Unable to determine the data directory (</span><span class="si">%s</span><span class="s">)&quot;</span> <span class="o">%</span> <span class="n">exc</span><span class="p">)</span>

      <span class="n">cached_descriptor_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">data_directory</span><span class="p">,</span> <span class="s">&quot;cached-microdescs&quot;</span><span class="p">)</span>

      <span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">data_directory</span><span class="p">):</span>
        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">OperationFailed</span><span class="p">(</span><span class="n">message</span> <span class="o">=</span> <span class="s">&quot;Data directory reported by tor doesn&#39;t exist (</span><span class="si">%s</span><span class="s">)&quot;</span> <span class="o">%</span> <span class="n">data_directory</span><span class="p">)</span>
      <span class="k">elif</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">exists</span><span class="p">(</span><span class="n">cached_descriptor_path</span><span class="p">):</span>
        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">OperationFailed</span><span class="p">(</span><span class="n">message</span> <span class="o">=</span> <span class="s">&quot;Data directory doens&#39;t contain cached microescriptors (</span><span class="si">%s</span><span class="s">)&quot;</span> <span class="o">%</span> <span class="n">cached_descriptor_path</span><span class="p">)</span>

      <span class="k">with</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">reader</span><span class="o">.</span><span class="n">DescriptorReader</span><span class="p">([</span><span class="n">cached_descriptor_path</span><span class="p">])</span> <span class="k">as</span> <span class="n">reader</span><span class="p">:</span>
        <span class="k">for</span> <span class="n">desc</span> <span class="ow">in</span> <span class="n">reader</span><span class="p">:</span>
          <span class="c"># It shouldn&#39;t be possible for these to be something other than</span>
          <span class="c"># microdescriptors but as the saying goes: trust but verify.</span>

          <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">desc</span><span class="p">,</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">microdescriptor</span><span class="o">.</span><span class="n">Microdescriptor</span><span class="p">):</span>
            <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">OperationFailed</span><span class="p">(</span><span class="n">message</span> <span class="o">=</span> <span class="s">&quot;BUG: Descriptor reader provided non-microdescriptor content (</span><span class="si">%s</span><span class="s">)&quot;</span> <span class="o">%</span> <span class="nb">type</span><span class="p">(</span><span class="n">desc</span><span class="p">))</span>

          <span class="k">yield</span> <span class="n">desc</span>
    <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
      <span class="k">if</span> <span class="n">default</span> <span class="o">==</span> <span class="n">UNDEFINED</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">exc</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">default</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
          <span class="k">for</span> <span class="n">entry</span> <span class="ow">in</span> <span class="n">default</span><span class="p">:</span>
            <span class="k">yield</span> <span class="n">entry</span>
</div>
<div class="viewcode-block" id="Controller.get_server_descriptor"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.get_server_descriptor">[docs]</a>  <span class="k">def</span> <span class="nf">get_server_descriptor</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">relay</span><span class="p">,</span> <span class="n">default</span> <span class="o">=</span> <span class="n">UNDEFINED</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Provides the server descriptor for the relay with the given fingerprint or</span>
<span class="sd">    nickname. If the relay identifier could be either a fingerprint *or*</span>
<span class="sd">    nickname then it&#39;s queried as a fingerprint.</span>

<span class="sd">    **As of Tor version 0.2.3.25 relays no longer get server descriptors by</span>
<span class="sd">    default.** It&#39;s advised that you use microdescriptors instead, but if you</span>
<span class="sd">    really need server descriptors then you can get them by setting</span>
<span class="sd">    &#39;UseMicrodescriptors 0&#39;.</span>

<span class="sd">    :param str relay: fingerprint or nickname of the relay to be queried</span>
<span class="sd">    :param object default: response if the query fails</span>

<span class="sd">    :returns: :class:`~stem.descriptor.server_descriptor.RelayDescriptor` for the given relay</span>

<span class="sd">    :raises:</span>
<span class="sd">      * :class:`stem.ControllerError` if unable to query the descriptor</span>
<span class="sd">      * **ValueError** if **relay** doesn&#39;t conform with the pattern for being</span>
<span class="sd">        a fingerprint or nickname</span>

<span class="sd">      An exception is only raised if we weren&#39;t provided a default response.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">try</span><span class="p">:</span>
      <span class="k">if</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">tor_tools</span><span class="o">.</span><span class="n">is_valid_fingerprint</span><span class="p">(</span><span class="n">relay</span><span class="p">):</span>
        <span class="n">query</span> <span class="o">=</span> <span class="s">&quot;desc/id/</span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">relay</span>
      <span class="k">elif</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">tor_tools</span><span class="o">.</span><span class="n">is_valid_nickname</span><span class="p">(</span><span class="n">relay</span><span class="p">):</span>
        <span class="n">query</span> <span class="o">=</span> <span class="s">&quot;desc/name/</span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">relay</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;&#39;</span><span class="si">%s</span><span class="s">&#39; isn&#39;t a valid fingerprint or nickname&quot;</span> <span class="o">%</span> <span class="n">relay</span><span class="p">)</span>

      <span class="n">desc_content</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_info</span><span class="p">(</span><span class="n">query</span><span class="p">,</span> <span class="n">get_bytes</span> <span class="o">=</span> <span class="bp">True</span><span class="p">)</span>
      <span class="k">return</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">server_descriptor</span><span class="o">.</span><span class="n">RelayDescriptor</span><span class="p">(</span><span class="n">desc_content</span><span class="p">)</span>
    <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
      <span class="k">if</span> <span class="n">default</span> <span class="o">==</span> <span class="n">UNDEFINED</span><span class="p">:</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_is_server_descriptors_available</span><span class="p">():</span>
          <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="n">SERVER_DESCRIPTORS_UNSUPPORTED</span><span class="p">)</span>

        <span class="k">raise</span> <span class="n">exc</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">default</span>
</div>
<div class="viewcode-block" id="Controller.get_server_descriptors"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.get_server_descriptors">[docs]</a>  <span class="k">def</span> <span class="nf">get_server_descriptors</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">default</span> <span class="o">=</span> <span class="n">UNDEFINED</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Provides an iterator for all of the server descriptors that tor presently</span>
<span class="sd">    knows about.</span>

<span class="sd">    **As of Tor version 0.2.3.25 relays no longer get server descriptors by</span>
<span class="sd">    default.** It&#39;s advised that you use microdescriptors instead, but if you</span>
<span class="sd">    really need server descriptors then you can get them by setting</span>
<span class="sd">    &#39;UseMicrodescriptors 0&#39;.</span>

<span class="sd">    :param list default: items to provide if the query fails</span>

<span class="sd">    :returns: iterates over</span>
<span class="sd">      :class:`~stem.descriptor.server_descriptor.RelayDescriptor` for relays in</span>
<span class="sd">      the tor network</span>

<span class="sd">    :raises: :class:`stem.ControllerError` if unable to query tor and no</span>
<span class="sd">      default was provided</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">try</span><span class="p">:</span>
      <span class="c"># TODO: We should iterate over the descriptors as they&#39;re read from the</span>
      <span class="c"># socket rather than reading the whole thing into memory.</span>
      <span class="c">#</span>
      <span class="c"># https://trac.torproject.org/8248</span>

      <span class="n">desc_content</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_info</span><span class="p">(</span><span class="s">&quot;desc/all-recent&quot;</span><span class="p">,</span> <span class="n">get_bytes</span> <span class="o">=</span> <span class="bp">True</span><span class="p">)</span>

      <span class="k">if</span> <span class="ow">not</span> <span class="n">desc_content</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_is_server_descriptors_available</span><span class="p">():</span>
        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="n">SERVER_DESCRIPTORS_UNSUPPORTED</span><span class="p">)</span>

      <span class="k">for</span> <span class="n">desc</span> <span class="ow">in</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">server_descriptor</span><span class="o">.</span><span class="n">_parse_file</span><span class="p">(</span><span class="n">io</span><span class="o">.</span><span class="n">BytesIO</span><span class="p">(</span><span class="n">desc_content</span><span class="p">)):</span>
        <span class="k">yield</span> <span class="n">desc</span>
    <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
      <span class="k">if</span> <span class="n">default</span> <span class="o">==</span> <span class="n">UNDEFINED</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">exc</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">default</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
          <span class="k">for</span> <span class="n">entry</span> <span class="ow">in</span> <span class="n">default</span><span class="p">:</span>
            <span class="k">yield</span> <span class="n">entry</span>
</div>
  <span class="k">def</span> <span class="nf">_is_server_descriptors_available</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Checks to see if tor server descriptors should be available or not.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_version</span><span class="p">()</span> <span class="o">&lt;</span> <span class="n">stem</span><span class="o">.</span><span class="n">version</span><span class="o">.</span><span class="n">Requirement</span><span class="o">.</span><span class="n">MICRODESCRIPTOR_IS_DEFAULT</span> <span class="ow">or</span> \
           <span class="bp">self</span><span class="o">.</span><span class="n">get_conf</span><span class="p">(</span><span class="s">&#39;UseMicrodescriptors&#39;</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="o">==</span> <span class="s">&#39;0&#39;</span>

<div class="viewcode-block" id="Controller.get_network_status"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.get_network_status">[docs]</a>  <span class="k">def</span> <span class="nf">get_network_status</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">relay</span><span class="p">,</span> <span class="n">default</span> <span class="o">=</span> <span class="n">UNDEFINED</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Provides the router status entry for the relay with the given fingerprint</span>
<span class="sd">    or nickname. If the relay identifier could be either a fingerprint *or*</span>
<span class="sd">    nickname then it&#39;s queried as a fingerprint.</span>

<span class="sd">    :param str relay: fingerprint or nickname of the relay to be queried</span>
<span class="sd">    :param object default: response if the query fails</span>

<span class="sd">    :returns: :class:`~stem.descriptor.router_status_entry.RouterStatusEntryV3`</span>
<span class="sd">      for the given relay</span>

<span class="sd">    :raises:</span>
<span class="sd">      * :class:`stem.ControllerError` if unable to query the descriptor</span>
<span class="sd">      * **ValueError** if **relay** doesn&#39;t conform with the pattern for being</span>
<span class="sd">        a fingerprint or nickname</span>

<span class="sd">      An exception is only raised if we weren&#39;t provided a default response.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="c"># TODO: It would be great to add support for v3 router status entries. This</span>
    <span class="c"># is pending...</span>
    <span class="c">#</span>
    <span class="c"># https://trac.torproject.org/7953</span>

    <span class="k">try</span><span class="p">:</span>
      <span class="k">if</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">tor_tools</span><span class="o">.</span><span class="n">is_valid_fingerprint</span><span class="p">(</span><span class="n">relay</span><span class="p">):</span>
        <span class="n">query</span> <span class="o">=</span> <span class="s">&quot;ns/id/</span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">relay</span>
      <span class="k">elif</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">tor_tools</span><span class="o">.</span><span class="n">is_valid_nickname</span><span class="p">(</span><span class="n">relay</span><span class="p">):</span>
        <span class="n">query</span> <span class="o">=</span> <span class="s">&quot;ns/name/</span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">relay</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;&#39;</span><span class="si">%s</span><span class="s">&#39; isn&#39;t a valid fingerprint or nickname&quot;</span> <span class="o">%</span> <span class="n">relay</span><span class="p">)</span>

      <span class="n">desc_content</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_info</span><span class="p">(</span><span class="n">query</span><span class="p">,</span> <span class="n">get_bytes</span> <span class="o">=</span> <span class="bp">True</span><span class="p">)</span>
      <span class="k">return</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">router_status_entry</span><span class="o">.</span><span class="n">RouterStatusEntryV3</span><span class="p">(</span><span class="n">desc_content</span><span class="p">)</span>
    <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
      <span class="k">if</span> <span class="n">default</span> <span class="o">==</span> <span class="n">UNDEFINED</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">exc</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">default</span>
</div>
<div class="viewcode-block" id="Controller.get_network_statuses"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.get_network_statuses">[docs]</a>  <span class="k">def</span> <span class="nf">get_network_statuses</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">default</span> <span class="o">=</span> <span class="n">UNDEFINED</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Provides an iterator for all of the router status entries that tor</span>
<span class="sd">    presently knows about.</span>

<span class="sd">    :param list default: items to provide if the query fails</span>

<span class="sd">    :returns: iterates over</span>
<span class="sd">      :class:`~stem.descriptor.router_status_entry.RouterStatusEntryV3` for</span>
<span class="sd">      relays in the tor network</span>

<span class="sd">    :raises: :class:`stem.ControllerError` if unable to query tor and no</span>
<span class="sd">      default was provided</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">try</span><span class="p">:</span>
      <span class="c"># TODO: We should iterate over the descriptors as they&#39;re read from the</span>
      <span class="c"># socket rather than reading the whole thing into memory.</span>
      <span class="c">#</span>
      <span class="c"># https://trac.torproject.org/8248</span>

      <span class="n">desc_content</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_info</span><span class="p">(</span><span class="s">&quot;ns/all&quot;</span><span class="p">,</span> <span class="n">get_bytes</span> <span class="o">=</span> <span class="bp">True</span><span class="p">)</span>

      <span class="n">desc_iterator</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">router_status_entry</span><span class="o">.</span><span class="n">_parse_file</span><span class="p">(</span>
        <span class="n">io</span><span class="o">.</span><span class="n">BytesIO</span><span class="p">(</span><span class="n">desc_content</span><span class="p">),</span>
        <span class="bp">True</span><span class="p">,</span>
        <span class="n">entry_class</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">descriptor</span><span class="o">.</span><span class="n">router_status_entry</span><span class="o">.</span><span class="n">RouterStatusEntryV3</span><span class="p">,</span>
      <span class="p">)</span>

      <span class="k">for</span> <span class="n">desc</span> <span class="ow">in</span> <span class="n">desc_iterator</span><span class="p">:</span>
        <span class="k">yield</span> <span class="n">desc</span>
    <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
      <span class="k">if</span> <span class="n">default</span> <span class="o">==</span> <span class="n">UNDEFINED</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">exc</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">default</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
          <span class="k">for</span> <span class="n">entry</span> <span class="ow">in</span> <span class="n">default</span><span class="p">:</span>
            <span class="k">yield</span> <span class="n">entry</span>
</div>
<div class="viewcode-block" id="Controller.get_conf"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.get_conf">[docs]</a>  <span class="k">def</span> <span class="nf">get_conf</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">param</span><span class="p">,</span> <span class="n">default</span> <span class="o">=</span> <span class="n">UNDEFINED</span><span class="p">,</span> <span class="n">multiple</span> <span class="o">=</span> <span class="bp">False</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Queries the current value for a configuration option. Some configuration</span>
<span class="sd">    options (like the ExitPolicy) can have multiple values. This provides a</span>
<span class="sd">    **list** with all of the values if **multiple** is **True**. Otherwise this</span>
<span class="sd">    will be a **str** with the first value.</span>

<span class="sd">    If provided with a **default** then that is provided if the configuration</span>
<span class="sd">    option was unset or the query fails (invalid configuration option, error</span>
<span class="sd">    response, control port closed, initiated, etc).</span>

<span class="sd">    If the configuration value is unset and no **default** was given then this</span>
<span class="sd">    provides **None** if **multiple** was **False** and an empty list if it was</span>
<span class="sd">    **True**.</span>

<span class="sd">    :param str param: configuration option to be queried</span>
<span class="sd">    :param object default: response if the option is unset or the query fails</span>
<span class="sd">    :param bool multiple: if **True** then provides a list with all of the</span>
<span class="sd">      present values (this is an empty list if the config option is unset)</span>

<span class="sd">    :returns:</span>
<span class="sd">      Response depends upon how we were called as follows...</span>

<span class="sd">      * **str** with the configuration value if **multiple** was **False**,</span>
<span class="sd">        **None** if it was unset</span>
<span class="sd">      * **list** with the response strings if multiple was **True**</span>
<span class="sd">      * default if one was provided and the configuration option was either</span>
<span class="sd">        unset or our call failed</span>

<span class="sd">    :raises:</span>
<span class="sd">      * :class:`stem.ControllerError` if the call fails and we weren&#39;t</span>
<span class="sd">        provided a default response</span>
<span class="sd">      * :class:`stem.InvalidArguments` if the configuration option</span>
<span class="sd">        requested was invalid</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="c"># Config options are case insensitive and don&#39;t contain whitespace. Using</span>
    <span class="c"># strip so the following check will catch whitespace-only params.</span>

    <span class="n">param</span> <span class="o">=</span> <span class="n">param</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="n">param</span><span class="p">:</span>
      <span class="k">return</span> <span class="n">default</span> <span class="k">if</span> <span class="n">default</span> <span class="o">!=</span> <span class="n">UNDEFINED</span> <span class="k">else</span> <span class="bp">None</span>

    <span class="n">entries</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_conf_map</span><span class="p">(</span><span class="n">param</span><span class="p">,</span> <span class="n">default</span><span class="p">,</span> <span class="n">multiple</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">_case_insensitive_lookup</span><span class="p">(</span><span class="n">entries</span><span class="p">,</span> <span class="n">param</span><span class="p">,</span> <span class="n">default</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="Controller.get_conf_map"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.get_conf_map">[docs]</a>  <span class="k">def</span> <span class="nf">get_conf_map</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">params</span><span class="p">,</span> <span class="n">default</span> <span class="o">=</span> <span class="n">UNDEFINED</span><span class="p">,</span> <span class="n">multiple</span> <span class="o">=</span> <span class="bp">True</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Similar to :func:`~stem.control.Controller.get_conf` but queries multiple</span>
<span class="sd">    configuration options, providing back a mapping of those options to their</span>
<span class="sd">    values.</span>

<span class="sd">    There are three use cases for GETCONF:</span>

<span class="sd">      1. a single value is provided (e.g. **ControlPort**)</span>
<span class="sd">      2. multiple values are provided for the option (e.g. **ExitPolicy**)</span>
<span class="sd">      3. a set of options that weren&#39;t necessarily requested are returned (for</span>
<span class="sd">         instance querying **HiddenServiceOptions** gives **HiddenServiceDir**,</span>
<span class="sd">         **HiddenServicePort**, etc)</span>

<span class="sd">    The vast majority of the options fall into the first two categories, in</span>
<span class="sd">    which case calling :func:`~stem.control.Controller.get_conf` is sufficient.</span>
<span class="sd">    However, for batch queries or the special options that give a set of values</span>
<span class="sd">    this provides back the full response. As of tor version 0.2.1.25</span>
<span class="sd">    **HiddenServiceOptions** was the only option that falls into the third</span>
<span class="sd">    category.</span>

<span class="sd">    :param str,list params: configuration option(s) to be queried</span>
<span class="sd">    :param object default: value for the mappings if the configuration option</span>
<span class="sd">      is either undefined or the query fails</span>
<span class="sd">    :param bool multiple: if **True** then the values provided are lists with</span>
<span class="sd">      all of the present values</span>

<span class="sd">    :returns:</span>
<span class="sd">      **dict** of the &#39;config key =&gt; value&#39; mappings. The value is a...</span>

<span class="sd">      * **str** if **multiple** is **False**, **None** if the configuration</span>
<span class="sd">        option is unset</span>
<span class="sd">      * **list** if **multiple** is **True**</span>
<span class="sd">      * the **default** if it was set and the value was either undefined or our</span>
<span class="sd">        lookup failed</span>

<span class="sd">    :raises:</span>
<span class="sd">      * :class:`stem.ControllerError` if the call fails and we weren&#39;t provided</span>
<span class="sd">        a default response</span>
<span class="sd">      * :class:`stem.InvalidArguments` if the configuration option requested</span>
<span class="sd">        was invalid</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="n">start_time</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>
    <span class="n">reply</span> <span class="o">=</span> <span class="p">{}</span>

    <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">params</span><span class="p">,</span> <span class="p">(</span><span class="nb">bytes</span><span class="p">,</span> <span class="nb">unicode</span><span class="p">)):</span>
      <span class="n">params</span> <span class="o">=</span> <span class="p">[</span><span class="n">params</span><span class="p">]</span>

    <span class="c"># remove strings which contain only whitespace</span>
    <span class="n">params</span> <span class="o">=</span> <span class="nb">filter</span><span class="p">(</span><span class="k">lambda</span> <span class="n">entry</span><span class="p">:</span> <span class="n">entry</span><span class="o">.</span><span class="n">strip</span><span class="p">(),</span> <span class="n">params</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">params</span> <span class="o">==</span> <span class="p">[]:</span>
      <span class="k">return</span> <span class="p">{}</span>

    <span class="c"># translate context sensitive options</span>
    <span class="n">lookup_params</span> <span class="o">=</span> <span class="nb">set</span><span class="p">([</span><span class="n">MAPPED_CONFIG_KEYS</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">entry</span><span class="p">,</span> <span class="n">entry</span><span class="p">)</span> <span class="k">for</span> <span class="n">entry</span> <span class="ow">in</span> <span class="n">params</span><span class="p">])</span>

    <span class="c"># check for cached results</span>

    <span class="n">from_cache</span> <span class="o">=</span> <span class="p">[</span><span class="n">param</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="k">for</span> <span class="n">param</span> <span class="ow">in</span> <span class="n">lookup_params</span><span class="p">]</span>
    <span class="n">cached_results</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_cache_map</span><span class="p">(</span><span class="n">from_cache</span><span class="p">,</span> <span class="s">&quot;getconf&quot;</span><span class="p">)</span>

    <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">cached_results</span><span class="p">:</span>
      <span class="n">user_expected_key</span> <span class="o">=</span> <span class="n">_case_insensitive_lookup</span><span class="p">(</span><span class="n">lookup_params</span><span class="p">,</span> <span class="n">key</span><span class="p">)</span>
      <span class="n">reply</span><span class="p">[</span><span class="n">user_expected_key</span><span class="p">]</span> <span class="o">=</span> <span class="n">cached_results</span><span class="p">[</span><span class="n">key</span><span class="p">]</span>
      <span class="n">lookup_params</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">user_expected_key</span><span class="p">)</span>

    <span class="c"># if everything was cached then short circuit making the query</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">lookup_params</span><span class="p">:</span>
      <span class="n">log</span><span class="o">.</span><span class="n">trace</span><span class="p">(</span><span class="s">&quot;GETCONF </span><span class="si">%s</span><span class="s"> (cache fetch)&quot;</span> <span class="o">%</span> <span class="s">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">reply</span><span class="o">.</span><span class="n">keys</span><span class="p">()))</span>
      <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_conf_dict_to_response</span><span class="p">(</span><span class="n">reply</span><span class="p">,</span> <span class="n">default</span><span class="p">,</span> <span class="n">multiple</span><span class="p">)</span>

    <span class="k">try</span><span class="p">:</span>
      <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s">&quot;GETCONF </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="s">&#39; &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">lookup_params</span><span class="p">))</span>
      <span class="n">stem</span><span class="o">.</span><span class="n">response</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="s">&quot;GETCONF&quot;</span><span class="p">,</span> <span class="n">response</span><span class="p">)</span>
      <span class="n">reply</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">entries</span><span class="p">)</span>

      <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_caching_enabled</span><span class="p">():</span>
        <span class="n">to_cache</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">((</span><span class="n">k</span><span class="o">.</span><span class="n">lower</span><span class="p">(),</span> <span class="n">v</span><span class="p">)</span> <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">response</span><span class="o">.</span><span class="n">entries</span><span class="o">.</span><span class="n">items</span><span class="p">())</span>

        <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">UNCACHEABLE_GETCONF_PARAMS</span><span class="p">:</span>
          <span class="k">if</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">to_cache</span><span class="p">:</span>
            <span class="k">del</span> <span class="n">to_cache</span><span class="p">[</span><span class="n">key</span><span class="p">]</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">_set_cache</span><span class="p">(</span><span class="n">to_cache</span><span class="p">,</span> <span class="s">&quot;getconf&quot;</span><span class="p">)</span>

      <span class="c"># Maps the entries back to the parameters that the user requested so the</span>
      <span class="c"># capitalization matches (ie, if they request &quot;exitpolicy&quot; then that</span>
      <span class="c"># should be the key rather than &quot;ExitPolicy&quot;). When the same</span>
      <span class="c"># configuration key is provided multiple times this determines the case</span>
      <span class="c"># based on the first and ignores the rest.</span>
      <span class="c">#</span>
      <span class="c"># This retains the tor provided camel casing of MAPPED_CONFIG_KEYS</span>
      <span class="c"># entries since the user didn&#39;t request those by their key, so we can&#39;t</span>
      <span class="c"># be sure what they wanted.</span>

      <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">reply</span><span class="p">:</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">key</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="ow">in</span> <span class="n">MAPPED_CONFIG_KEYS</span><span class="o">.</span><span class="n">values</span><span class="p">():</span>
          <span class="n">user_expected_key</span> <span class="o">=</span> <span class="n">_case_insensitive_lookup</span><span class="p">(</span><span class="n">params</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">key</span><span class="p">)</span>

          <span class="k">if</span> <span class="n">key</span> <span class="o">!=</span> <span class="n">user_expected_key</span><span class="p">:</span>
            <span class="n">reply</span><span class="p">[</span><span class="n">user_expected_key</span><span class="p">]</span> <span class="o">=</span> <span class="n">reply</span><span class="p">[</span><span class="n">key</span><span class="p">]</span>
            <span class="k">del</span> <span class="n">reply</span><span class="p">[</span><span class="n">key</span><span class="p">]</span>

      <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&quot;GETCONF </span><span class="si">%s</span><span class="s"> (runtime: </span><span class="si">%0.4f</span><span class="s">)&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="s">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">lookup_params</span><span class="p">),</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">start_time</span><span class="p">))</span>
      <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_conf_dict_to_response</span><span class="p">(</span><span class="n">reply</span><span class="p">,</span> <span class="n">default</span><span class="p">,</span> <span class="n">multiple</span><span class="p">)</span>
    <span class="k">except</span> <span class="n">stem</span><span class="o">.</span><span class="n">ControllerError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
      <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&quot;GETCONF </span><span class="si">%s</span><span class="s"> (failed: </span><span class="si">%s</span><span class="s">)&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="s">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">lookup_params</span><span class="p">),</span> <span class="n">exc</span><span class="p">))</span>

      <span class="k">if</span> <span class="n">default</span> <span class="o">!=</span> <span class="n">UNDEFINED</span><span class="p">:</span>
        <span class="k">return</span> <span class="nb">dict</span><span class="p">((</span><span class="n">param</span><span class="p">,</span> <span class="n">default</span><span class="p">)</span> <span class="k">for</span> <span class="n">param</span> <span class="ow">in</span> <span class="n">params</span><span class="p">)</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">exc</span>
</div>
  <span class="k">def</span> <span class="nf">_get_conf_dict_to_response</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">config_dict</span><span class="p">,</span> <span class="n">default</span><span class="p">,</span> <span class="n">multiple</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Translates a dictionary of &#39;config key =&gt; [value1, value2...]&#39; into the</span>
<span class="sd">    return value of :func:`~stem.control.Controller.get_conf_map`, taking into</span>
<span class="sd">    account what the caller requested.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="n">return_dict</span> <span class="o">=</span> <span class="p">{}</span>

    <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">values</span> <span class="ow">in</span> <span class="n">config_dict</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
      <span class="k">if</span> <span class="n">values</span> <span class="o">==</span> <span class="p">[]:</span>
        <span class="c"># config option was unset</span>
        <span class="k">if</span> <span class="n">default</span> <span class="o">!=</span> <span class="n">UNDEFINED</span><span class="p">:</span>
          <span class="n">return_dict</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">default</span>
        <span class="k">else</span><span class="p">:</span>
          <span class="n">return_dict</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">if</span> <span class="n">multiple</span> <span class="k">else</span> <span class="bp">None</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="n">return_dict</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">values</span> <span class="k">if</span> <span class="n">multiple</span> <span class="k">else</span> <span class="n">values</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>

    <span class="k">return</span> <span class="n">return_dict</span>

<div class="viewcode-block" id="Controller.set_conf"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.set_conf">[docs]</a>  <span class="k">def</span> <span class="nf">set_conf</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">param</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Changes the value of a tor configuration option. Our value can be any of</span>
<span class="sd">    the following...</span>

<span class="sd">    * a string to set a single value</span>
<span class="sd">    * a list of strings to set a series of values (for instance the ExitPolicy)</span>
<span class="sd">    * None to either set the value to 0/NULL</span>

<span class="sd">    :param str param: configuration option to be set</span>
<span class="sd">    :param str,list value: value to set the parameter to</span>

<span class="sd">    :raises:</span>
<span class="sd">      * :class:`stem.ControllerError` if the call fails</span>
<span class="sd">      * :class:`stem.InvalidArguments` if configuration options</span>
<span class="sd">        requested was invalid</span>
<span class="sd">      * :class:`stem.InvalidRequest` if the configuration setting is</span>
<span class="sd">        impossible or if there&#39;s a syntax error in the configuration values</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="bp">self</span><span class="o">.</span><span class="n">set_options</span><span class="p">({</span><span class="n">param</span><span class="p">:</span> <span class="n">value</span><span class="p">},</span> <span class="bp">False</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="Controller.reset_conf"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.reset_conf">[docs]</a>  <span class="k">def</span> <span class="nf">reset_conf</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">params</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Reverts one or more parameters to their default values.</span>

<span class="sd">    :param str params: configuration option to be reset</span>

<span class="sd">    :raises:</span>
<span class="sd">      * :class:`stem.ControllerError` if the call fails</span>
<span class="sd">      * :class:`stem.InvalidArguments` if configuration options requested was invalid</span>
<span class="sd">      * :class:`stem.InvalidRequest` if the configuration setting is</span>
<span class="sd">        impossible or if there&#39;s a syntax error in the configuration values</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="bp">self</span><span class="o">.</span><span class="n">set_options</span><span class="p">(</span><span class="nb">dict</span><span class="p">([(</span><span class="n">entry</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="k">for</span> <span class="n">entry</span> <span class="ow">in</span> <span class="n">params</span><span class="p">]),</span> <span class="bp">True</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="Controller.set_options"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.set_options">[docs]</a>  <span class="k">def</span> <span class="nf">set_options</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">params</span><span class="p">,</span> <span class="n">reset</span> <span class="o">=</span> <span class="bp">False</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Changes multiple tor configuration options via either a SETCONF or</span>
<span class="sd">    RESETCONF query. Both behave identically unless our value is None, in which</span>
<span class="sd">    case SETCONF sets the value to 0 or NULL, and RESETCONF returns it to its</span>
<span class="sd">    default value. This accepts str, list, or None values in a similar fashion</span>
<span class="sd">    to :func:`~stem.control.Controller.set_conf`. For example...</span>

<span class="sd">    ::</span>

<span class="sd">      my_controller.set_options({</span>
<span class="sd">        &quot;Nickname&quot;: &quot;caerSidi&quot;,</span>
<span class="sd">        &quot;ExitPolicy&quot;: [&quot;accept *:80&quot;, &quot;accept *:443&quot;, &quot;reject *:*&quot;],</span>
<span class="sd">        &quot;ContactInfo&quot;: &quot;caerSidi-exit@someplace.com&quot;,</span>
<span class="sd">        &quot;Log&quot;: None,</span>
<span class="sd">      })</span>

<span class="sd">    The params can optionally be a list of key/value tuples, though the only</span>
<span class="sd">    reason this type of argument would be useful is for hidden service</span>
<span class="sd">    configuration (those options are order dependent).</span>

<span class="sd">    :param dict,list params: mapping of configuration options to the values</span>
<span class="sd">      we&#39;re setting it to</span>
<span class="sd">    :param bool reset: issues a RESETCONF, returning **None** values to their</span>
<span class="sd">      defaults if **True**</span>

<span class="sd">    :raises:</span>
<span class="sd">      * :class:`stem.ControllerError` if the call fails</span>
<span class="sd">      * :class:`stem.InvalidArguments` if configuration options</span>
<span class="sd">        requested was invalid</span>
<span class="sd">      * :class:`stem.InvalidRequest` if the configuration setting is</span>
<span class="sd">        impossible or if there&#39;s a syntax error in the configuration values</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="n">start_time</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span>

    <span class="c"># constructs the SETCONF or RESETCONF query</span>
    <span class="n">query_comp</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;RESETCONF&quot;</span> <span class="k">if</span> <span class="n">reset</span> <span class="k">else</span> <span class="s">&quot;SETCONF&quot;</span><span class="p">]</span>

    <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">params</span><span class="p">,</span> <span class="nb">dict</span><span class="p">):</span>
      <span class="n">params</span> <span class="o">=</span> <span class="n">params</span><span class="o">.</span><span class="n">items</span><span class="p">()</span>

    <span class="k">for</span> <span class="n">param</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">params</span><span class="p">:</span>
      <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
        <span class="n">query_comp</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&quot;</span><span class="si">%s</span><span class="s">=</span><span class="se">\&quot;</span><span class="si">%s</span><span class="se">\&quot;</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">param</span><span class="p">,</span> <span class="n">value</span><span class="o">.</span><span class="n">strip</span><span class="p">()))</span>
      <span class="k">elif</span> <span class="n">value</span><span class="p">:</span>
        <span class="n">query_comp</span><span class="o">.</span><span class="n">extend</span><span class="p">([</span><span class="s">&quot;</span><span class="si">%s</span><span class="s">=</span><span class="se">\&quot;</span><span class="si">%s</span><span class="se">\&quot;</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">param</span><span class="p">,</span> <span class="n">val</span><span class="o">.</span><span class="n">strip</span><span class="p">())</span> <span class="k">for</span> <span class="n">val</span> <span class="ow">in</span> <span class="n">value</span><span class="p">])</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="n">query_comp</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">param</span><span class="p">)</span>

    <span class="n">query</span> <span class="o">=</span> <span class="s">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">query_comp</span><span class="p">)</span>
    <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">query</span><span class="p">)</span>
    <span class="n">stem</span><span class="o">.</span><span class="n">response</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="s">&quot;SINGLELINE&quot;</span><span class="p">,</span> <span class="n">response</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">is_ok</span><span class="p">():</span>
      <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&quot;</span><span class="si">%s</span><span class="s"> (runtime: </span><span class="si">%0.4f</span><span class="s">)&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">query</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="n">start_time</span><span class="p">))</span>

      <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_caching_enabled</span><span class="p">():</span>
        <span class="n">to_cache</span> <span class="o">=</span> <span class="p">{}</span>

        <span class="k">for</span> <span class="n">param</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">params</span><span class="p">:</span>
          <span class="n">param</span> <span class="o">=</span> <span class="n">param</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>

          <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="p">(</span><span class="nb">bytes</span><span class="p">,</span> <span class="nb">unicode</span><span class="p">)):</span>
            <span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="n">value</span><span class="p">]</span>

          <span class="n">to_cache</span><span class="p">[</span><span class="n">param</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>

          <span class="k">if</span> <span class="n">param</span> <span class="o">==</span> <span class="s">&quot;exitpolicy&quot;</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">_set_cache</span><span class="p">({</span><span class="s">&quot;exitpolicy&quot;</span><span class="p">:</span> <span class="bp">None</span><span class="p">})</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">_set_cache</span><span class="p">(</span><span class="n">to_cache</span><span class="p">,</span> <span class="s">&quot;getconf&quot;</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
      <span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&quot;</span><span class="si">%s</span><span class="s"> (failed, code: </span><span class="si">%s</span><span class="s">, message: </span><span class="si">%s</span><span class="s">)&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">query</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="p">))</span>

      <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span> <span class="o">==</span> <span class="s">&quot;552&quot;</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&quot;Unrecognized option: Unknown option &#39;&quot;</span><span class="p">):</span>
          <span class="n">key</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="p">[</span><span class="mi">37</span><span class="p">:</span><span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s">&quot;</span><span class="se">\&#39;</span><span class="s">&quot;</span><span class="p">,</span> <span class="mi">37</span><span class="p">)]</span>
          <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">InvalidArguments</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="p">,</span> <span class="p">[</span><span class="n">key</span><span class="p">])</span>
        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">InvalidRequest</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="p">)</span>
      <span class="k">elif</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&quot;513&quot;</span><span class="p">,</span> <span class="s">&quot;553&quot;</span><span class="p">):</span>
        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">InvalidRequest</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="p">)</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">(</span><span class="s">&quot;Returned unexpected status code: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="Controller.add_event_listener"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.add_event_listener">[docs]</a>  <span class="k">def</span> <span class="nf">add_event_listener</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">listener</span><span class="p">,</span> <span class="o">*</span><span class="n">events</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Directs further tor controller events to a given function. The function is</span>
<span class="sd">    expected to take a single argument, which is a</span>
<span class="sd">    :class:`~stem.response.events.Event` subclass. For instance the following</span>
<span class="sd">    would print the bytes sent and received by tor over five seconds...</span>

<span class="sd">    ::</span>

<span class="sd">      import time</span>
<span class="sd">      from stem.control import Controller, EventType</span>

<span class="sd">      def print_bw(event):</span>
<span class="sd">        print &quot;sent: %i, received: %i&quot; % (event.written, event.read)</span>

<span class="sd">      with Controller.from_port(port = 9051) as controller:</span>
<span class="sd">        controller.authenticate()</span>
<span class="sd">        controller.add_event_listener(print_bw, EventType.BW)</span>
<span class="sd">        time.sleep(5)</span>

<span class="sd">    If a new control connection is initialized then this listener will be</span>
<span class="sd">    reattached.</span>

<span class="sd">    :param functor listener: function to be called when an event is received</span>
<span class="sd">    :param stem.control.EventType events: event types to be listened for</span>

<span class="sd">    :raises: :class:`stem.ProtocolError` if unable to set the events</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="c"># first checking that tor supports these event types</span>
    <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">_event_listeners_lock</span><span class="p">:</span>
      <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_authenticated</span><span class="p">():</span>
        <span class="k">for</span> <span class="n">event_type</span> <span class="ow">in</span> <span class="n">events</span><span class="p">:</span>
          <span class="n">event_version</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">response</span><span class="o">.</span><span class="n">events</span><span class="o">.</span><span class="n">EVENT_TYPE_TO_CLASS</span><span class="p">[</span><span class="n">event_type</span><span class="p">]</span><span class="o">.</span><span class="n">_VERSION_ADDED</span>

          <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_version</span><span class="p">()</span> <span class="o">&lt;</span> <span class="n">event_version</span><span class="p">:</span>
            <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">InvalidRequest</span><span class="p">(</span><span class="mi">552</span><span class="p">,</span> <span class="s">&quot;</span><span class="si">%s</span><span class="s"> event requires Tor version </span><span class="si">%s</span><span class="s"> or later&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">event_type</span><span class="p">,</span> <span class="n">event_version</span><span class="p">))</span>

      <span class="k">for</span> <span class="n">event_type</span> <span class="ow">in</span> <span class="n">events</span><span class="p">:</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">_event_listeners</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">event_type</span><span class="p">,</span> <span class="p">[])</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">listener</span><span class="p">)</span>

      <span class="n">failed_events</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_attach_listeners</span><span class="p">()[</span><span class="mi">1</span><span class="p">]</span>

      <span class="c"># restricted the failures to just things we requested</span>
      <span class="n">failed_events</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span><span class="n">failed_events</span><span class="p">)</span><span class="o">.</span><span class="n">intersection</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">events</span><span class="p">))</span>

      <span class="k">if</span> <span class="n">failed_events</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">(</span><span class="s">&quot;SETEVENTS rejected </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="s">&quot;, &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">failed_events</span><span class="p">))</span>
</div>
<div class="viewcode-block" id="Controller.remove_event_listener"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.remove_event_listener">[docs]</a>  <span class="k">def</span> <span class="nf">remove_event_listener</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">listener</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Stops a listener from being notified of further tor events.</span>

<span class="sd">    :param stem.control.EventListener listener: listener to be removed</span>

<span class="sd">    :raises: :class:`stem.ProtocolError` if unable to set the events</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">_event_listeners_lock</span><span class="p">:</span>
      <span class="n">event_types_changed</span> <span class="o">=</span> <span class="bp">False</span>

      <span class="k">for</span> <span class="n">event_type</span><span class="p">,</span> <span class="n">event_listeners</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_event_listeners</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
        <span class="k">if</span> <span class="n">listener</span> <span class="ow">in</span> <span class="n">event_listeners</span><span class="p">:</span>
          <span class="n">event_listeners</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">listener</span><span class="p">)</span>

          <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">event_listeners</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">event_types_changed</span> <span class="o">=</span> <span class="bp">True</span>
            <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_event_listeners</span><span class="p">[</span><span class="n">event_type</span><span class="p">]</span>

      <span class="k">if</span> <span class="n">event_types_changed</span><span class="p">:</span>
        <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s">&quot;SETEVENTS </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="s">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_event_listeners</span><span class="o">.</span><span class="n">keys</span><span class="p">()))</span>

        <span class="k">if</span> <span class="ow">not</span> <span class="n">response</span><span class="o">.</span><span class="n">is_ok</span><span class="p">():</span>
          <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">(</span><span class="s">&quot;SETEVENTS received unexpected response</span><span class="se">\n</span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">response</span><span class="p">)</span>
</div>
  <span class="k">def</span> <span class="nf">_get_cache</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">param</span><span class="p">,</span> <span class="n">namespace</span> <span class="o">=</span> <span class="bp">None</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Queries our request cache for the given key.</span>

<span class="sd">    :param str param: key to be queried</span>
<span class="sd">    :param str namespace: namespace in which to check for the key</span>

<span class="sd">    :returns: cached value corresponding to key or **None** if the key wasn&#39;t found</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_cache_map</span><span class="p">([</span><span class="n">param</span><span class="p">],</span> <span class="n">namespace</span><span class="p">)</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">param</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>

  <span class="k">def</span> <span class="nf">_get_cache_map</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">params</span><span class="p">,</span> <span class="n">namespace</span> <span class="o">=</span> <span class="bp">None</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Queries our request cache for multiple entries.</span>

<span class="sd">    :param list params: keys to be queried</span>
<span class="sd">    :param str namespace: namespace in which to check for the keys</span>

<span class="sd">    :returns: **dict** of &#39;param =&gt; cached value&#39; pairs of keys present in cache</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">_cache_lock</span><span class="p">:</span>
      <span class="n">cached_values</span> <span class="o">=</span> <span class="p">{}</span>

      <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_caching_enabled</span><span class="p">():</span>
        <span class="k">for</span> <span class="n">param</span> <span class="ow">in</span> <span class="n">params</span><span class="p">:</span>
          <span class="k">if</span> <span class="n">namespace</span><span class="p">:</span>
            <span class="n">cache_key</span> <span class="o">=</span> <span class="s">&quot;</span><span class="si">%s</span><span class="s">.</span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">namespace</span><span class="p">,</span> <span class="n">param</span><span class="p">)</span>
          <span class="k">else</span><span class="p">:</span>
            <span class="n">cache_key</span> <span class="o">=</span> <span class="n">param</span>

          <span class="k">if</span> <span class="n">cache_key</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_request_cache</span><span class="p">:</span>
            <span class="n">cached_values</span><span class="p">[</span><span class="n">param</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_request_cache</span><span class="p">[</span><span class="n">cache_key</span><span class="p">]</span>

      <span class="k">return</span> <span class="n">cached_values</span>

  <span class="k">def</span> <span class="nf">_set_cache</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">params</span><span class="p">,</span> <span class="n">namespace</span> <span class="o">=</span> <span class="bp">None</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Sets the given request cache entries. If the new cache value is **None**</span>
<span class="sd">    then it is removed from our cache.</span>

<span class="sd">    :param dict params: **dict** of &#39;cache_key =&gt; value&#39; pairs to be cached</span>
<span class="sd">    :param str namespace: namespace for the keys</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">_cache_lock</span><span class="p">:</span>
      <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_caching_enabled</span><span class="p">():</span>
        <span class="k">return</span>

      <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">params</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
        <span class="k">if</span> <span class="n">namespace</span><span class="p">:</span>
          <span class="n">cache_key</span> <span class="o">=</span> <span class="s">&quot;</span><span class="si">%s</span><span class="s">.</span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">namespace</span><span class="p">,</span> <span class="n">key</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
          <span class="n">cache_key</span> <span class="o">=</span> <span class="n">key</span>

        <span class="k">if</span> <span class="n">value</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
          <span class="k">if</span> <span class="n">cache_key</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_request_cache</span><span class="p">:</span>
            <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_request_cache</span><span class="p">[</span><span class="n">cache_key</span><span class="p">]</span>
        <span class="k">else</span><span class="p">:</span>
          <span class="bp">self</span><span class="o">.</span><span class="n">_request_cache</span><span class="p">[</span><span class="n">cache_key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>

<div class="viewcode-block" id="Controller.is_caching_enabled"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.is_caching_enabled">[docs]</a>  <span class="k">def</span> <span class="nf">is_caching_enabled</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    **True** if caching has been enabled, **False** otherwise.</span>

<span class="sd">    :returns: bool to indicate if caching is enabled</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_is_caching_enabled</span>
</div>
<div class="viewcode-block" id="Controller.set_caching"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.set_caching">[docs]</a>  <span class="k">def</span> <span class="nf">set_caching</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">enabled</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Enables or disables caching of information retrieved from tor.</span>

<span class="sd">    :param bool enabled: **True** to enable caching, **False** to disable it</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="bp">self</span><span class="o">.</span><span class="n">_is_caching_enabled</span> <span class="o">=</span> <span class="n">enabled</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_is_caching_enabled</span><span class="p">:</span>
      <span class="bp">self</span><span class="o">.</span><span class="n">clear_cache</span><span class="p">()</span>
</div>
<div class="viewcode-block" id="Controller.clear_cache"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.clear_cache">[docs]</a>  <span class="k">def</span> <span class="nf">clear_cache</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Drops any cached results.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">_cache_lock</span><span class="p">:</span>
      <span class="bp">self</span><span class="o">.</span><span class="n">_request_cache</span> <span class="o">=</span> <span class="p">{}</span>
      <span class="bp">self</span><span class="o">.</span><span class="n">_geoip_failure_count</span> <span class="o">=</span> <span class="mi">0</span>
</div>
<div class="viewcode-block" id="Controller.load_conf"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.load_conf">[docs]</a>  <span class="k">def</span> <span class="nf">load_conf</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">configtext</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Sends the configuration text to Tor and loads it as if it has been read from</span>
<span class="sd">    the torrc.</span>

<span class="sd">    :param str configtext: the configuration text</span>

<span class="sd">    :raises: :class:`stem.ControllerError` if the call fails</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s">&quot;LOADCONF</span><span class="se">\n</span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">configtext</span><span class="p">)</span>
    <span class="n">stem</span><span class="o">.</span><span class="n">response</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="s">&quot;SINGLELINE&quot;</span><span class="p">,</span> <span class="n">response</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&quot;552&quot;</span><span class="p">,</span> <span class="s">&quot;553&quot;</span><span class="p">):</span>
      <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span> <span class="o">==</span> <span class="s">&quot;552&quot;</span> <span class="ow">and</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&quot;Invalid config file: Failed to parse/validate config: Unknown option&quot;</span><span class="p">):</span>
        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">InvalidArguments</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="p">,</span> <span class="p">[</span><span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="p">[</span><span class="mi">70</span><span class="p">:</span><span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s">&#39;.&#39;</span><span class="p">,</span> <span class="mi">70</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]])</span>
      <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">InvalidRequest</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="p">)</span>
    <span class="k">elif</span> <span class="ow">not</span> <span class="n">response</span><span class="o">.</span><span class="n">is_ok</span><span class="p">():</span>
      <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">(</span><span class="s">&quot;+LOADCONF Received unexpected response</span><span class="se">\n</span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="n">response</span><span class="p">))</span>
</div>
<div class="viewcode-block" id="Controller.save_conf"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.save_conf">[docs]</a>  <span class="k">def</span> <span class="nf">save_conf</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Saves the current configuration options into the active torrc file.</span>

<span class="sd">    :raises:</span>
<span class="sd">      * :class:`stem.ControllerError` if the call fails</span>
<span class="sd">      * :class:`stem.OperationFailed` if the client is unable to save</span>
<span class="sd">        the configuration file</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s">&quot;SAVECONF&quot;</span><span class="p">)</span>
    <span class="n">stem</span><span class="o">.</span><span class="n">response</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="s">&quot;SINGLELINE&quot;</span><span class="p">,</span> <span class="n">response</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">is_ok</span><span class="p">():</span>
      <span class="k">return</span> <span class="bp">True</span>
    <span class="k">elif</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span> <span class="o">==</span> <span class="s">&quot;551&quot;</span><span class="p">:</span>
      <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">OperationFailed</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
      <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">(</span><span class="s">&quot;SAVECONF returned unexpected response code&quot;</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="Controller.is_feature_enabled"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.is_feature_enabled">[docs]</a>  <span class="k">def</span> <span class="nf">is_feature_enabled</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">feature</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Checks if a control connection feature is enabled. These features can be</span>
<span class="sd">    enabled using :func:`~stem.control.Controller.enable_feature`.</span>

<span class="sd">    :param str feature: feature to be checked</span>

<span class="sd">    :returns: **True** if feature is enabled, **False** otherwise</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="n">feature</span> <span class="o">=</span> <span class="n">feature</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span>

    <span class="k">if</span> <span class="n">feature</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_enabled_features</span><span class="p">:</span>
      <span class="k">return</span> <span class="bp">True</span>
    <span class="k">else</span><span class="p">:</span>
      <span class="c"># check if this feature is on by default</span>
      <span class="n">defaulted_version</span> <span class="o">=</span> <span class="bp">None</span>

      <span class="k">if</span> <span class="n">feature</span> <span class="o">==</span> <span class="s">&quot;EXTENDED_EVENTS&quot;</span><span class="p">:</span>
        <span class="n">defaulted_version</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">version</span><span class="o">.</span><span class="n">Requirement</span><span class="o">.</span><span class="n">FEATURE_EXTENDED_EVENTS</span>
      <span class="k">elif</span> <span class="n">feature</span> <span class="o">==</span> <span class="s">&quot;VERBOSE_NAMES&quot;</span><span class="p">:</span>
        <span class="n">defaulted_version</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">version</span><span class="o">.</span><span class="n">Requirement</span><span class="o">.</span><span class="n">FEATURE_VERBOSE_NAMES</span>

      <span class="k">if</span> <span class="n">defaulted_version</span><span class="p">:</span>
        <span class="n">our_version</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_version</span><span class="p">(</span><span class="bp">None</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">our_version</span> <span class="ow">and</span> <span class="n">our_version</span> <span class="o">&gt;=</span> <span class="n">defaulted_version</span><span class="p">:</span>
          <span class="bp">self</span><span class="o">.</span><span class="n">_enabled_features</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">feature</span><span class="p">)</span>

      <span class="k">return</span> <span class="n">feature</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_enabled_features</span>
</div>
<div class="viewcode-block" id="Controller.enable_feature"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.enable_feature">[docs]</a>  <span class="k">def</span> <span class="nf">enable_feature</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">features</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Enables features that are disabled by default to maintain backward</span>
<span class="sd">    compatibility. Once enabled, a feature cannot be disabled and a new</span>
<span class="sd">    control connection must be opened to get a connection with the feature</span>
<span class="sd">    disabled. Feature names are case-insensitive.</span>

<span class="sd">    The following features are currently accepted:</span>

<span class="sd">      * EXTENDED_EVENTS - Requests the extended event syntax</span>
<span class="sd">      * VERBOSE_NAMES - Replaces ServerID with LongName in events and GETINFO results</span>

<span class="sd">    :param str,list features: a single feature or a list of features to be enabled</span>

<span class="sd">    :raises:</span>
<span class="sd">      * :class:`stem.ControllerError` if the call fails</span>
<span class="sd">      * :class:`stem.InvalidArguments` if features passed were invalid</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">features</span><span class="p">,</span> <span class="p">(</span><span class="nb">bytes</span><span class="p">,</span> <span class="nb">unicode</span><span class="p">)):</span>
      <span class="n">features</span> <span class="o">=</span> <span class="p">[</span><span class="n">features</span><span class="p">]</span>

    <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s">&quot;USEFEATURE </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="s">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">features</span><span class="p">))</span>
    <span class="n">stem</span><span class="o">.</span><span class="n">response</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="s">&quot;SINGLELINE&quot;</span><span class="p">,</span> <span class="n">response</span><span class="p">)</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="n">response</span><span class="o">.</span><span class="n">is_ok</span><span class="p">():</span>
      <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span> <span class="o">==</span> <span class="s">&quot;552&quot;</span><span class="p">:</span>
        <span class="n">invalid_feature</span> <span class="o">=</span> <span class="p">[]</span>

        <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&quot;Unrecognized feature </span><span class="se">\&quot;</span><span class="s">&quot;</span><span class="p">):</span>
          <span class="n">invalid_feature</span> <span class="o">=</span> <span class="p">[</span><span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="p">[</span><span class="mi">22</span><span class="p">:</span><span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s">&quot;</span><span class="se">\&quot;</span><span class="s">&quot;</span><span class="p">,</span> <span class="mi">22</span><span class="p">)]]</span>

        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">InvalidArguments</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="p">,</span> <span class="n">invalid_feature</span><span class="p">)</span>

      <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">(</span><span class="s">&quot;USEFEATURE provided an invalid response code: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">)</span>

    <span class="bp">self</span><span class="o">.</span><span class="n">_enabled_features</span> <span class="o">+=</span> <span class="p">[</span><span class="n">entry</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span> <span class="k">for</span> <span class="n">entry</span> <span class="ow">in</span> <span class="n">features</span><span class="p">]</span>
</div>
<div class="viewcode-block" id="Controller.get_circuit"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.get_circuit">[docs]</a>  <span class="k">def</span> <span class="nf">get_circuit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">circuit_id</span><span class="p">,</span> <span class="n">default</span> <span class="o">=</span> <span class="n">UNDEFINED</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Provides a circuit presently available from tor.</span>

<span class="sd">    :param int circuit_id: circuit to be fetched</span>
<span class="sd">    :param object default: response if the query fails</span>

<span class="sd">    :returns: :class:`stem.response.events.CircuitEvent` for the given circuit</span>

<span class="sd">    :raises:</span>
<span class="sd">      * :class:`stem.ControllerError` if the call fails</span>
<span class="sd">      * **ValueError** if the circuit doesn&#39;t exist</span>

<span class="sd">      An exception is only raised if we weren&#39;t provided a default response.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">try</span><span class="p">:</span>
      <span class="k">for</span> <span class="n">circ</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_circuits</span><span class="p">():</span>
        <span class="k">if</span> <span class="n">circ</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">circuit_id</span><span class="p">:</span>
          <span class="k">return</span> <span class="n">circ</span>

      <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;Tor presently does not have a circuit with the id of &#39;</span><span class="si">%s</span><span class="s">&#39;&quot;</span> <span class="o">%</span> <span class="n">circuit_id</span><span class="p">)</span>
    <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
      <span class="k">if</span> <span class="n">default</span> <span class="o">==</span> <span class="n">UNDEFINED</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">exc</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">default</span>
</div>
<div class="viewcode-block" id="Controller.get_circuits"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.get_circuits">[docs]</a>  <span class="k">def</span> <span class="nf">get_circuits</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">default</span> <span class="o">=</span> <span class="n">UNDEFINED</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Provides tor&#39;s currently available circuits.</span>

<span class="sd">    :param object default: response if the query fails</span>

<span class="sd">    :returns: **list** of :class:`stem.response.events.CircuitEvent` for our circuits</span>

<span class="sd">    :raises: :class:`stem.ControllerError` if the call fails and no default was provided</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">try</span><span class="p">:</span>
      <span class="n">circuits</span> <span class="o">=</span> <span class="p">[]</span>
      <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_info</span><span class="p">(</span><span class="s">&quot;circuit-status&quot;</span><span class="p">)</span>

      <span class="k">for</span> <span class="n">circ</span> <span class="ow">in</span> <span class="n">response</span><span class="o">.</span><span class="n">splitlines</span><span class="p">():</span>
        <span class="n">circ_message</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">socket</span><span class="o">.</span><span class="n">recv_message</span><span class="p">(</span><span class="n">StringIO</span><span class="o">.</span><span class="n">StringIO</span><span class="p">(</span><span class="s">&quot;650 CIRC &quot;</span> <span class="o">+</span> <span class="n">circ</span> <span class="o">+</span> <span class="s">&quot;</span><span class="se">\r\n</span><span class="s">&quot;</span><span class="p">))</span>
        <span class="n">stem</span><span class="o">.</span><span class="n">response</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="s">&quot;EVENT&quot;</span><span class="p">,</span> <span class="n">circ_message</span><span class="p">,</span> <span class="n">arrived_at</span> <span class="o">=</span> <span class="mi">0</span><span class="p">)</span>
        <span class="n">circuits</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">circ_message</span><span class="p">)</span>

      <span class="k">return</span> <span class="n">circuits</span>
    <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
      <span class="k">if</span> <span class="n">default</span> <span class="o">==</span> <span class="n">UNDEFINED</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">exc</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">default</span>
</div>
<div class="viewcode-block" id="Controller.new_circuit"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.new_circuit">[docs]</a>  <span class="k">def</span> <span class="nf">new_circuit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">purpose</span> <span class="o">=</span> <span class="s">&quot;general&quot;</span><span class="p">,</span> <span class="n">await_build</span> <span class="o">=</span> <span class="bp">False</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Requests a new circuit. If the path isn&#39;t provided, one is automatically</span>
<span class="sd">    selected.</span>

<span class="sd">    :param list,str path: one or more relays to make a circuit through</span>
<span class="sd">    :param str purpose: &quot;general&quot; or &quot;controller&quot;</span>
<span class="sd">    :param bool await_build: blocks until the circuit is built if **True**</span>

<span class="sd">    :returns: str of the circuit id of the newly created circuit</span>

<span class="sd">    :raises: :class:`stem.ControllerError` if the call fails</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">extend_circuit</span><span class="p">(</span><span class="s">&#39;0&#39;</span><span class="p">,</span> <span class="n">path</span><span class="p">,</span> <span class="n">purpose</span><span class="p">,</span> <span class="n">await_build</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="Controller.extend_circuit"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.extend_circuit">[docs]</a>  <span class="k">def</span> <span class="nf">extend_circuit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">circuit_id</span> <span class="o">=</span> <span class="s">&quot;0&quot;</span><span class="p">,</span> <span class="n">path</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">purpose</span> <span class="o">=</span> <span class="s">&quot;general&quot;</span><span class="p">,</span> <span class="n">await_build</span> <span class="o">=</span> <span class="bp">False</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Either requests the creation of a new circuit or extends an existing one.</span>

<span class="sd">    When called with a circuit value of zero (the default) a new circuit is</span>
<span class="sd">    created, and when non-zero the circuit with that id is extended. If the</span>
<span class="sd">    path isn&#39;t provided, one is automatically selected.</span>

<span class="sd">    A python interpreter session used to create circuits could look like this...</span>

<span class="sd">    ::</span>

<span class="sd">      &gt;&gt;&gt; control.extend_circuit(&#39;0&#39;, [&quot;718BCEA286B531757ACAFF93AE04910EA73DE617&quot;, &quot;30BAB8EE7606CBD12F3CC269AE976E0153E7A58D&quot;, &quot;2765D8A8C4BBA3F89585A9FFE0E8575615880BEB&quot;])</span>
<span class="sd">      19</span>
<span class="sd">      &gt;&gt;&gt; control.extend_circuit(&#39;0&#39;)</span>
<span class="sd">      20</span>
<span class="sd">      &gt;&gt;&gt; print control.get_info(&#39;circuit-status&#39;)</span>
<span class="sd">      20 EXTENDED $718BCEA286B531757ACAFF93AE04910EA73DE617=KsmoinOK,$649F2D0ACF418F7CFC6539AB2257EB2D5297BAFA=Eskimo BUILD_FLAGS=NEED_CAPACITY PURPOSE=GENERAL TIME_CREATED=2012-12-06T13:51:11.433755</span>
<span class="sd">      19 BUILT $718BCEA286B531757ACAFF93AE04910EA73DE617=KsmoinOK,$30BAB8EE7606CBD12F3CC269AE976E0153E7A58D=Pascal1,$2765D8A8C4BBA3F89585A9FFE0E8575615880BEB=Anthracite PURPOSE=GENERAL TIME_CREATED=2012-12-06T13:50:56.969938</span>

<span class="sd">    :param str circuit_id: id of a circuit to be extended</span>
<span class="sd">    :param list,str path: one or more relays to make a circuit through, this is</span>
<span class="sd">      required if the circuit id is non-zero</span>
<span class="sd">    :param str purpose: &quot;general&quot; or &quot;controller&quot;</span>
<span class="sd">    :param bool await_build: blocks until the circuit is built if **True**</span>

<span class="sd">    :returns: str of the circuit id of the created or extended circuit</span>

<span class="sd">    :raises:</span>
<span class="sd">      * :class:`stem.InvalidRequest` if one of the parameters were invalid</span>
<span class="sd">      * :class:`stem.CircuitExtensionFailed` if we were waiting for the circuit</span>
<span class="sd">        to build but it failed</span>
<span class="sd">      * :class:`stem.ControllerError` if the call fails</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="c"># Attaches a temporary listener for CIRC events if we&#39;ll be waiting for it</span>
    <span class="c"># to build. This is icky, but we can&#39;t reliably do this via polling since</span>
    <span class="c"># we then can&#39;t get the failure if it can&#39;t be created.</span>

    <span class="n">circ_queue</span><span class="p">,</span> <span class="n">circ_listener</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="bp">None</span>

    <span class="k">if</span> <span class="n">await_build</span><span class="p">:</span>
      <span class="n">circ_queue</span> <span class="o">=</span> <span class="n">Queue</span><span class="o">.</span><span class="n">Queue</span><span class="p">()</span>

      <span class="k">def</span> <span class="nf">circ_listener</span><span class="p">(</span><span class="n">event</span><span class="p">):</span>
        <span class="n">circ_queue</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>

      <span class="bp">self</span><span class="o">.</span><span class="n">add_event_listener</span><span class="p">(</span><span class="n">circ_listener</span><span class="p">,</span> <span class="n">EventType</span><span class="o">.</span><span class="n">CIRC</span><span class="p">)</span>

    <span class="k">try</span><span class="p">:</span>
      <span class="c"># we might accidently get integer circuit ids</span>
      <span class="n">circuit_id</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">circuit_id</span><span class="p">)</span>

      <span class="k">if</span> <span class="n">path</span> <span class="ow">is</span> <span class="bp">None</span> <span class="ow">and</span> <span class="n">circuit_id</span> <span class="o">==</span> <span class="s">&#39;0&#39;</span><span class="p">:</span>
        <span class="n">path_opt_version</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">version</span><span class="o">.</span><span class="n">Requirement</span><span class="o">.</span><span class="n">EXTENDCIRCUIT_PATH_OPTIONAL</span>

        <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_version</span><span class="p">()</span> <span class="o">&gt;=</span> <span class="n">path_opt_version</span><span class="p">:</span>
          <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">InvalidRequest</span><span class="p">(</span><span class="mi">512</span><span class="p">,</span> <span class="s">&quot;EXTENDCIRCUIT requires the path prior to version </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">path_opt_version</span><span class="p">)</span>

      <span class="n">args</span> <span class="o">=</span> <span class="p">[</span><span class="n">circuit_id</span><span class="p">]</span>

      <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="p">(</span><span class="nb">bytes</span><span class="p">,</span> <span class="nb">unicode</span><span class="p">)):</span>
        <span class="n">path</span> <span class="o">=</span> <span class="p">[</span><span class="n">path</span><span class="p">]</span>

      <span class="k">if</span> <span class="n">path</span><span class="p">:</span>
        <span class="n">args</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&quot;,&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">path</span><span class="p">))</span>

      <span class="k">if</span> <span class="n">purpose</span><span class="p">:</span>
        <span class="n">args</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&quot;purpose=</span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">purpose</span><span class="p">)</span>

      <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s">&quot;EXTENDCIRCUIT </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="s">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">args</span><span class="p">))</span>
      <span class="n">stem</span><span class="o">.</span><span class="n">response</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="s">&quot;SINGLELINE&quot;</span><span class="p">,</span> <span class="n">response</span><span class="p">)</span>

      <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;512&#39;</span><span class="p">,</span> <span class="s">&#39;552&#39;</span><span class="p">):</span>
        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">InvalidRequest</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="p">)</span>
      <span class="k">elif</span> <span class="ow">not</span> <span class="n">response</span><span class="o">.</span><span class="n">is_ok</span><span class="p">():</span>
        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">(</span><span class="s">&quot;EXTENDCIRCUIT returned unexpected response code: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">)</span>

      <span class="k">if</span> <span class="ow">not</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&quot;EXTENDED &quot;</span><span class="p">):</span>
        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">(</span><span class="s">&quot;EXTENDCIRCUIT response invalid:</span><span class="se">\n</span><span class="si">%s</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">response</span><span class="p">)</span>

      <span class="n">new_circuit</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&quot; &quot;</span><span class="p">,</span> <span class="mi">1</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span>

      <span class="k">if</span> <span class="n">await_build</span><span class="p">:</span>
        <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
          <span class="n">circ</span> <span class="o">=</span> <span class="n">circ_queue</span><span class="o">.</span><span class="n">get</span><span class="p">()</span>

          <span class="k">if</span> <span class="n">circ</span><span class="o">.</span><span class="n">id</span> <span class="o">==</span> <span class="n">new_circuit</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">circ</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="n">CircStatus</span><span class="o">.</span><span class="n">BUILT</span><span class="p">:</span>
              <span class="k">break</span>
            <span class="k">elif</span> <span class="n">circ</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="n">CircStatus</span><span class="o">.</span><span class="n">FAILED</span><span class="p">:</span>
              <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">CircuitExtensionFailed</span><span class="p">(</span><span class="s">&quot;Circuit failed to be created: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">circ</span><span class="o">.</span><span class="n">reason</span><span class="p">,</span> <span class="n">circ</span><span class="p">)</span>
            <span class="k">elif</span> <span class="n">circ</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="n">CircStatus</span><span class="o">.</span><span class="n">CLOSED</span><span class="p">:</span>
              <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">CircuitExtensionFailed</span><span class="p">(</span><span class="s">&quot;Circuit was closed prior to build&quot;</span><span class="p">,</span> <span class="n">circ</span><span class="p">)</span>

      <span class="k">return</span> <span class="n">new_circuit</span>
    <span class="k">finally</span><span class="p">:</span>
      <span class="k">if</span> <span class="n">circ_listener</span><span class="p">:</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">remove_event_listener</span><span class="p">(</span><span class="n">circ_listener</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="Controller.repurpose_circuit"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.repurpose_circuit">[docs]</a>  <span class="k">def</span> <span class="nf">repurpose_circuit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">circuit_id</span><span class="p">,</span> <span class="n">purpose</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Changes a circuit&#39;s purpose. Currently, two purposes are recognized...</span>
<span class="sd">      * general</span>
<span class="sd">      * controller</span>

<span class="sd">    :param str circuit_id: id of the circuit whose purpose is to be changed</span>
<span class="sd">    :param str purpose: purpose (either &quot;general&quot; or &quot;controller&quot;)</span>

<span class="sd">    :raises: :class:`stem.InvalidArguments` if the circuit doesn&#39;t exist or if the purpose was invalid</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s">&quot;SETCIRCUITPURPOSE </span><span class="si">%s</span><span class="s"> purpose=</span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">circuit_id</span><span class="p">,</span> <span class="n">purpose</span><span class="p">))</span>
    <span class="n">stem</span><span class="o">.</span><span class="n">response</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="s">&quot;SINGLELINE&quot;</span><span class="p">,</span> <span class="n">response</span><span class="p">)</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="n">response</span><span class="o">.</span><span class="n">is_ok</span><span class="p">():</span>
      <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span> <span class="o">==</span> <span class="s">&quot;552&quot;</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">InvalidRequest</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="p">)</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">(</span><span class="s">&quot;SETCIRCUITPURPOSE returned unexpected response code: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="Controller.close_circuit"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.close_circuit">[docs]</a>  <span class="k">def</span> <span class="nf">close_circuit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">circuit_id</span><span class="p">,</span> <span class="n">flag</span> <span class="o">=</span> <span class="s">&#39;&#39;</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Closes the specified circuit.</span>

<span class="sd">    :param str circuit_id: id of the circuit to be closed</span>
<span class="sd">    :param str flag: optional value to modify closing, the only flag available</span>
<span class="sd">      is &quot;IfUnused&quot; which will not close the circuit unless it is unused</span>

<span class="sd">    :raises: :class:`stem.InvalidArguments` if the circuit is unknown</span>
<span class="sd">    :raises: :class:`stem.InvalidRequest` if not enough information is provided</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s">&quot;CLOSECIRCUIT </span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">circuit_id</span><span class="p">,</span> <span class="n">flag</span><span class="p">))</span>
    <span class="n">stem</span><span class="o">.</span><span class="n">response</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="s">&quot;SINGLELINE&quot;</span><span class="p">,</span> <span class="n">response</span><span class="p">)</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="n">response</span><span class="o">.</span><span class="n">is_ok</span><span class="p">():</span>
      <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;512&#39;</span><span class="p">,</span> <span class="s">&#39;552&#39;</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&quot;Unknown circuit &quot;</span><span class="p">):</span>
          <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">InvalidArguments</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="p">,</span> <span class="p">[</span><span class="n">circuit_id</span><span class="p">])</span>
        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">InvalidRequest</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="p">)</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">(</span><span class="s">&quot;CLOSECIRCUIT returned unexpected response code: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="Controller.get_streams"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.get_streams">[docs]</a>  <span class="k">def</span> <span class="nf">get_streams</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">default</span> <span class="o">=</span> <span class="n">UNDEFINED</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Provides the list of streams tor is currently handling.</span>

<span class="sd">    :param object default: response if the query fails</span>

<span class="sd">    :returns: list of :class:`stem.response.events.StreamEvent` objects</span>

<span class="sd">    :raises: :class:`stem.ControllerError` if the call fails and no default was</span>
<span class="sd">      provided</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">try</span><span class="p">:</span>
      <span class="n">streams</span> <span class="o">=</span> <span class="p">[]</span>
      <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_info</span><span class="p">(</span><span class="s">&quot;stream-status&quot;</span><span class="p">)</span>

      <span class="k">for</span> <span class="n">stream</span> <span class="ow">in</span> <span class="n">response</span><span class="o">.</span><span class="n">splitlines</span><span class="p">():</span>
        <span class="n">message</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">socket</span><span class="o">.</span><span class="n">recv_message</span><span class="p">(</span><span class="n">StringIO</span><span class="o">.</span><span class="n">StringIO</span><span class="p">(</span><span class="s">&quot;650 STREAM &quot;</span> <span class="o">+</span> <span class="n">stream</span> <span class="o">+</span> <span class="s">&quot;</span><span class="se">\r\n</span><span class="s">&quot;</span><span class="p">))</span>
        <span class="n">stem</span><span class="o">.</span><span class="n">response</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="s">&quot;EVENT&quot;</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">arrived_at</span> <span class="o">=</span> <span class="mi">0</span><span class="p">)</span>
        <span class="n">streams</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>

      <span class="k">return</span> <span class="n">streams</span>
    <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
      <span class="k">if</span> <span class="n">default</span> <span class="o">==</span> <span class="n">UNDEFINED</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">exc</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">default</span>
</div>
<div class="viewcode-block" id="Controller.attach_stream"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.attach_stream">[docs]</a>  <span class="k">def</span> <span class="nf">attach_stream</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">stream_id</span><span class="p">,</span> <span class="n">circuit_id</span><span class="p">,</span> <span class="n">exiting_hop</span> <span class="o">=</span> <span class="bp">None</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Attaches a stream to a circuit.</span>

<span class="sd">    Note: Tor attaches streams to circuits automatically unless the</span>
<span class="sd">    __LeaveStreamsUnattached configuration variable is set to &quot;1&quot;</span>

<span class="sd">    :param str stream_id: id of the stream that must be attached</span>
<span class="sd">    :param str circuit_id: id of the circuit to which it must be attached</span>
<span class="sd">    :param int exiting_hop: hop in the circuit where traffic should exit</span>

<span class="sd">    :raises:</span>
<span class="sd">      * :class:`stem.InvalidRequest` if the stream or circuit id were unrecognized</span>
<span class="sd">      * :class:`stem.UnsatisfiableRequest` if the stream isn&#39;t in a state where it can be attached</span>
<span class="sd">      * :class:`stem.OperationFailed` if the stream couldn&#39;t be attached for any other reason</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="n">query</span> <span class="o">=</span> <span class="s">&quot;ATTACHSTREAM </span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">stream_id</span><span class="p">,</span> <span class="n">circuit_id</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">exiting_hop</span><span class="p">:</span>
      <span class="n">query</span> <span class="o">+=</span> <span class="s">&quot; HOP=</span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">exiting_hop</span>

    <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">query</span><span class="p">)</span>
    <span class="n">stem</span><span class="o">.</span><span class="n">response</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="s">&quot;SINGLELINE&quot;</span><span class="p">,</span> <span class="n">response</span><span class="p">)</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="n">response</span><span class="o">.</span><span class="n">is_ok</span><span class="p">():</span>
      <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span> <span class="o">==</span> <span class="s">&#39;552&#39;</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">InvalidRequest</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="p">)</span>
      <span class="k">elif</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span> <span class="o">==</span> <span class="s">&#39;551&#39;</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">OperationFailed</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="p">)</span>
      <span class="k">elif</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span> <span class="o">==</span> <span class="s">&#39;555&#39;</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">UnsatisfiableRequest</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="p">)</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">(</span><span class="s">&quot;ATTACHSTREAM returned unexpected response code: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="Controller.close_stream"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.close_stream">[docs]</a>  <span class="k">def</span> <span class="nf">close_stream</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">stream_id</span><span class="p">,</span> <span class="n">reason</span> <span class="o">=</span> <span class="n">stem</span><span class="o">.</span><span class="n">RelayEndReason</span><span class="o">.</span><span class="n">MISC</span><span class="p">,</span> <span class="n">flag</span> <span class="o">=</span> <span class="s">&#39;&#39;</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Closes the specified stream.</span>

<span class="sd">    :param str stream_id: id of the stream to be closed</span>
<span class="sd">    :param stem.RelayEndReason reason: reason the stream is closing</span>
<span class="sd">    :param str flag: not currently used</span>

<span class="sd">    :raises: :class:`stem.InvalidArguments` if the stream or reason are not recognized</span>
<span class="sd">    :raises: :class:`stem.InvalidRequest` if the stream and/or reason are missing</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="c"># there&#39;s a single value offset between RelayEndReason.index_of() and the</span>
    <span class="c"># value that tor expects since tor&#39;s value starts with the index of one</span>

    <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s">&quot;CLOSESTREAM </span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s"> </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">stream_id</span><span class="p">,</span> <span class="n">stem</span><span class="o">.</span><span class="n">RelayEndReason</span><span class="o">.</span><span class="n">index_of</span><span class="p">(</span><span class="n">reason</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">flag</span><span class="p">))</span>
    <span class="n">stem</span><span class="o">.</span><span class="n">response</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="s">&quot;SINGLELINE&quot;</span><span class="p">,</span> <span class="n">response</span><span class="p">)</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="n">response</span><span class="o">.</span><span class="n">is_ok</span><span class="p">():</span>
      <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span> <span class="ow">in</span> <span class="p">(</span><span class="s">&#39;512&#39;</span><span class="p">,</span> <span class="s">&#39;552&#39;</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&quot;Unknown stream &quot;</span><span class="p">):</span>
          <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">InvalidArguments</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="p">,</span> <span class="p">[</span><span class="n">stream_id</span><span class="p">])</span>
        <span class="k">elif</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&quot;Unrecognized reason &quot;</span><span class="p">):</span>
          <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">InvalidArguments</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="p">,</span> <span class="p">[</span><span class="n">reason</span><span class="p">])</span>
        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">InvalidRequest</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="p">)</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">(</span><span class="s">&quot;CLOSESTREAM returned unexpected response code: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="Controller.signal"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.signal">[docs]</a>  <span class="k">def</span> <span class="nf">signal</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">signal</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Sends a signal to the Tor client.</span>

<span class="sd">    :param stem.Signal signal: type of signal to be sent</span>

<span class="sd">    :raises: :class:`stem.InvalidArguments` if signal provided wasn&#39;t recognized</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s">&quot;SIGNAL </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">signal</span><span class="p">)</span>
    <span class="n">stem</span><span class="o">.</span><span class="n">response</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="s">&quot;SINGLELINE&quot;</span><span class="p">,</span> <span class="n">response</span><span class="p">)</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="n">response</span><span class="o">.</span><span class="n">is_ok</span><span class="p">():</span>
      <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span> <span class="o">==</span> <span class="s">&quot;552&quot;</span><span class="p">:</span>
        <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">InvalidArguments</span><span class="p">(</span><span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">,</span> <span class="n">response</span><span class="o">.</span><span class="n">message</span><span class="p">,</span> <span class="p">[</span><span class="n">signal</span><span class="p">])</span>

      <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">(</span><span class="s">&quot;SIGNAL response contained unrecognized status code: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">response</span><span class="o">.</span><span class="n">code</span><span class="p">)</span>
</div>
<div class="viewcode-block" id="Controller.is_geoip_unavailable"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.is_geoip_unavailable">[docs]</a>  <span class="k">def</span> <span class="nf">is_geoip_unavailable</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Provides **True** if we&#39;ve concluded hat our geoip database is unavailable,</span>
<span class="sd">    **False** otherwise. This is determined by having our &#39;GETINFO</span>
<span class="sd">    ip-to-country/\*&#39; lookups fail so this will default to **False** if we</span>
<span class="sd">    aren&#39;t making those queries.</span>

<span class="sd">    Geoip failures will be untracked if caching is disabled.</span>

<span class="sd">    :returns: **bool** to indicate if we&#39;ve concluded our geoip database to be</span>
<span class="sd">      unavailable or not</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_geoip_failure_count</span> <span class="o">&gt;=</span> <span class="n">GEOIP_FAILURE_THRESHOLD</span>
</div>
<div class="viewcode-block" id="Controller.map_address"><a class="viewcode-back" href="../../api/control.html#stem.control.Controller.map_address">[docs]</a>  <span class="k">def</span> <span class="nf">map_address</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">mapping</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Map addresses to replacement addresses. Tor replaces subseqent connections</span>
<span class="sd">    to the original addresses with the replacement addresses.</span>

<span class="sd">    If the original address is a null address, i.e., one of &quot;0.0.0.0&quot;, &quot;::0&quot;, or</span>
<span class="sd">    &quot;.&quot; Tor picks an original address itself and returns it in the reply. If the</span>
<span class="sd">    original address is already mapped to a different address the mapping is</span>
<span class="sd">    removed.</span>

<span class="sd">    :param dict mapping: mapping of original addresses to replacement addresses</span>

<span class="sd">    :raises:</span>
<span class="sd">      * :class:`stem.InvalidRequest` if the addresses are malformed</span>
<span class="sd">      * :class:`stem.OperationFailed` if Tor couldn&#39;t fulfill the request</span>

<span class="sd">    :returns: **dict** with &#39;original -&gt; replacement&#39; address mappings</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="n">mapaddress_arg</span> <span class="o">=</span> <span class="s">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="s">&quot;</span><span class="si">%s</span><span class="s">=</span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span> <span class="k">for</span> <span class="p">(</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span> <span class="ow">in</span> <span class="n">mapping</span><span class="o">.</span><span class="n">items</span><span class="p">()])</span>
    <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s">&quot;MAPADDRESS </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="n">mapaddress_arg</span><span class="p">)</span>
    <span class="n">stem</span><span class="o">.</span><span class="n">response</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="s">&quot;MAPADDRESS&quot;</span><span class="p">,</span> <span class="n">response</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">response</span><span class="o">.</span><span class="n">entries</span>
</div>
  <span class="k">def</span> <span class="nf">_post_authentication</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="nb">super</span><span class="p">(</span><span class="n">Controller</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">_post_authentication</span><span class="p">()</span>

    <span class="c"># try to re-attach event listeners to the new instance</span>

    <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">_event_listeners_lock</span><span class="p">:</span>
      <span class="k">try</span><span class="p">:</span>
        <span class="n">failed_events</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_attach_listeners</span><span class="p">()[</span><span class="mi">1</span><span class="p">]</span>

        <span class="k">if</span> <span class="n">failed_events</span><span class="p">:</span>
          <span class="c"># remove our listeners for these so we don&#39;t keep failing</span>
          <span class="k">for</span> <span class="n">event_type</span> <span class="ow">in</span> <span class="n">failed_events</span><span class="p">:</span>
            <span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_event_listeners</span><span class="p">[</span><span class="n">event_type</span><span class="p">]</span>

          <span class="n">logging_id</span> <span class="o">=</span> <span class="s">&quot;stem.controller.event_reattach-</span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="s">&quot;-&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">failed_events</span><span class="p">)</span>
          <span class="n">log</span><span class="o">.</span><span class="n">log_once</span><span class="p">(</span><span class="n">logging_id</span><span class="p">,</span> <span class="n">log</span><span class="o">.</span><span class="n">WARN</span><span class="p">,</span> <span class="s">&quot;We were unable to re-attach our event listeners to the new tor instance for: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="s">&quot;, &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">failed_events</span><span class="p">))</span>
      <span class="k">except</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
        <span class="n">log</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s">&quot;Unable to issue the SETEVENTS request to re-attach our listeners (</span><span class="si">%s</span><span class="s">)&quot;</span> <span class="o">%</span> <span class="n">exc</span><span class="p">)</span>

    <span class="c"># issue TAKEOWNERSHIP if we&#39;re the owning process for this tor instance</span>

    <span class="n">owning_pid</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_conf</span><span class="p">(</span><span class="s">&quot;__OwningControllerProcess&quot;</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">owning_pid</span> <span class="o">==</span> <span class="nb">str</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">getpid</span><span class="p">())</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_socket</span><span class="p">()</span><span class="o">.</span><span class="n">is_localhost</span><span class="p">():</span>
      <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s">&quot;TAKEOWNERSHIP&quot;</span><span class="p">)</span>
      <span class="n">stem</span><span class="o">.</span><span class="n">response</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="s">&quot;SINGLELINE&quot;</span><span class="p">,</span> <span class="n">response</span><span class="p">)</span>

      <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">is_ok</span><span class="p">():</span>
        <span class="c"># Now that tor is tracking our ownership of the process via the control</span>
        <span class="c"># connection, we can stop having it check for us via our pid.</span>

        <span class="k">try</span><span class="p">:</span>
          <span class="bp">self</span><span class="o">.</span><span class="n">reset_conf</span><span class="p">(</span><span class="s">&quot;__OwningControllerProcess&quot;</span><span class="p">)</span>
        <span class="k">except</span> <span class="n">stem</span><span class="o">.</span><span class="n">ControllerError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
          <span class="n">log</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s">&quot;We were unable to reset tor&#39;s __OwningControllerProcess configuration. It will continue to periodically check if our pid exists. (</span><span class="si">%s</span><span class="s">)&quot;</span> <span class="o">%</span> <span class="n">exc</span><span class="p">)</span>
      <span class="k">else</span><span class="p">:</span>
        <span class="n">log</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s">&quot;We were unable assert ownership of tor through TAKEOWNERSHIP, despite being configured to be the owning process through __OwningControllerProcess. (</span><span class="si">%s</span><span class="s">)&quot;</span> <span class="o">%</span> <span class="n">response</span><span class="p">)</span>

  <span class="k">def</span> <span class="nf">_handle_event</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">event_message</span><span class="p">):</span>
    <span class="n">stem</span><span class="o">.</span><span class="n">response</span><span class="o">.</span><span class="n">convert</span><span class="p">(</span><span class="s">&quot;EVENT&quot;</span><span class="p">,</span> <span class="n">event_message</span><span class="p">,</span> <span class="n">arrived_at</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">time</span><span class="p">())</span>

    <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">_event_listeners_lock</span><span class="p">:</span>
      <span class="k">for</span> <span class="n">event_type</span><span class="p">,</span> <span class="n">event_listeners</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_event_listeners</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
        <span class="k">if</span> <span class="n">event_type</span> <span class="o">==</span> <span class="n">event_message</span><span class="o">.</span><span class="n">type</span><span class="p">:</span>
          <span class="k">for</span> <span class="n">listener</span> <span class="ow">in</span> <span class="n">event_listeners</span><span class="p">:</span>
            <span class="n">listener</span><span class="p">(</span><span class="n">event_message</span><span class="p">)</span>

  <span class="k">def</span> <span class="nf">_attach_listeners</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">    Attempts to subscribe to the self._event_listeners events from tor. This is</span>
<span class="sd">    a no-op if we&#39;re not presently authenticated.</span>

<span class="sd">    :returns: tuple of the form (set_events, failed_events)</span>

<span class="sd">    :raises: :class:`stem.ControllerError` if unable to make our request to tor</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="n">set_events</span><span class="p">,</span> <span class="n">failed_events</span> <span class="o">=</span> <span class="p">[],</span> <span class="p">[]</span>

    <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">_event_listeners_lock</span><span class="p">:</span>
      <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_authenticated</span><span class="p">():</span>
        <span class="c"># try to set them all</span>
        <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s">&quot;SETEVENTS </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="s">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_event_listeners</span><span class="o">.</span><span class="n">keys</span><span class="p">()))</span>

        <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">is_ok</span><span class="p">():</span>
          <span class="n">set_events</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_event_listeners</span><span class="o">.</span><span class="n">keys</span><span class="p">()</span>
        <span class="k">else</span><span class="p">:</span>
          <span class="c"># One of the following likely happened...</span>
          <span class="c">#</span>
          <span class="c"># * Our user attached listeners before having an authenticated</span>
          <span class="c">#   connection, so we couldn&#39;t check if we met the version</span>
          <span class="c">#   requirement.</span>
          <span class="c">#</span>
          <span class="c"># * User attached listeners to one tor instance, then connected us to</span>
          <span class="c">#   an older tor instancce.</span>
          <span class="c">#</span>
          <span class="c"># * Some other controller hiccup (far less likely).</span>
          <span class="c">#</span>
          <span class="c"># See if we can set some subset of our events.</span>

          <span class="k">for</span> <span class="n">event</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_event_listeners</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
            <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s">&quot;SETEVENTS </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="s">&quot; &quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">set_events</span> <span class="o">+</span> <span class="p">[</span><span class="n">event</span><span class="p">]))</span>

            <span class="k">if</span> <span class="n">response</span><span class="o">.</span><span class="n">is_ok</span><span class="p">():</span>
              <span class="n">set_events</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
              <span class="n">failed_events</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>

    <span class="k">return</span> <span class="p">(</span><span class="n">set_events</span><span class="p">,</span> <span class="n">failed_events</span><span class="p">)</span>

</div>
<span class="k">def</span> <span class="nf">_parse_circ_path</span><span class="p">(</span><span class="n">path</span><span class="p">):</span>
  <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">  Parses a circuit path as a list of **(fingerprint, nickname)** tuples. Tor</span>
<span class="sd">  circuit paths are defined as being of the form...</span>

<span class="sd">  ::</span>

<span class="sd">    Path = LongName *(&quot;,&quot; LongName)</span>
<span class="sd">    LongName = Fingerprint [ ( &quot;=&quot; / &quot;~&quot; ) Nickname ]</span>

<span class="sd">    example:</span>
<span class="sd">    $999A226EBED397F331B612FE1E4CFAE5C1F201BA=piyaz</span>

<span class="sd">  ... *unless* this is prior to tor version 0.2.2.1 with the VERBOSE_NAMES</span>
<span class="sd">  feature turned off (or before version 0.1.2.2 where the feature was</span>
<span class="sd">  introduced). In that case either the fingerprint or nickname in the tuple</span>
<span class="sd">  will be **None**, depending on which is missing.</span>

<span class="sd">  ::</span>

<span class="sd">    Path = ServerID *(&quot;,&quot; ServerID)</span>
<span class="sd">    ServerID = Nickname / Fingerprint</span>

<span class="sd">    example:</span>
<span class="sd">    $E57A476CD4DFBD99B4EE52A100A58610AD6E80B9,hamburgerphone,PrivacyRepublic14</span>

<span class="sd">  :param str path: circuit path to be parsed</span>

<span class="sd">  :returns: list of **(fingerprint, nickname)** tuples, fingerprints do not have a proceeding &#39;$&#39;</span>

<span class="sd">  :raises: :class:`stem.ProtocolError` if the path is malformed</span>
<span class="sd">  &quot;&quot;&quot;</span>

  <span class="k">if</span> <span class="n">path</span><span class="p">:</span>
    <span class="k">try</span><span class="p">:</span>
      <span class="k">return</span> <span class="p">[</span><span class="n">_parse_circ_entry</span><span class="p">(</span><span class="n">entry</span><span class="p">)</span> <span class="k">for</span> <span class="n">entry</span> <span class="ow">in</span> <span class="n">path</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;,&#39;</span><span class="p">)]</span>
    <span class="k">except</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
      <span class="c"># include the path with the exception</span>
      <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">(</span><span class="s">&quot;</span><span class="si">%s</span><span class="s">: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">exc</span><span class="p">,</span> <span class="n">path</span><span class="p">))</span>
  <span class="k">else</span><span class="p">:</span>
    <span class="k">return</span> <span class="p">[]</span>


<span class="k">def</span> <span class="nf">_parse_circ_entry</span><span class="p">(</span><span class="n">entry</span><span class="p">):</span>
  <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">  Parses a single relay&#39;s &#39;LongName&#39; or &#39;ServerID&#39;. See the</span>
<span class="sd">  :func:`~_stem.control._parse_circ_path` function for more information.</span>

<span class="sd">  :param str entry: relay information to be parsed</span>

<span class="sd">  :returns: **(fingerprint, nickname)** tuple</span>

<span class="sd">  :raises: :class:`stem.ProtocolError` if the entry is malformed</span>
<span class="sd">  &quot;&quot;&quot;</span>

  <span class="k">if</span> <span class="s">&#39;=&#39;</span> <span class="ow">in</span> <span class="n">entry</span><span class="p">:</span>
    <span class="c"># common case</span>
    <span class="n">fingerprint</span><span class="p">,</span> <span class="n">nickname</span> <span class="o">=</span> <span class="n">entry</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;=&#39;</span><span class="p">)</span>
  <span class="k">elif</span> <span class="s">&#39;~&#39;</span> <span class="ow">in</span> <span class="n">entry</span><span class="p">:</span>
    <span class="c"># this is allowed for by the spec, but I&#39;ve never seen it used</span>
    <span class="n">fingerprint</span><span class="p">,</span> <span class="n">nickname</span> <span class="o">=</span> <span class="n">entry</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;~&#39;</span><span class="p">)</span>
  <span class="k">elif</span> <span class="n">entry</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s">&#39;$&#39;</span><span class="p">:</span>
    <span class="c"># old style, fingerprint only</span>
    <span class="n">fingerprint</span><span class="p">,</span> <span class="n">nickname</span> <span class="o">=</span> <span class="n">entry</span><span class="p">,</span> <span class="bp">None</span>
  <span class="k">else</span><span class="p">:</span>
    <span class="c"># old style, nickname only</span>
    <span class="n">fingerprint</span><span class="p">,</span> <span class="n">nickname</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">entry</span>

  <span class="k">if</span> <span class="n">fingerprint</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">tor_tools</span><span class="o">.</span><span class="n">is_valid_fingerprint</span><span class="p">(</span><span class="n">fingerprint</span><span class="p">,</span> <span class="bp">True</span><span class="p">):</span>
      <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">(</span><span class="s">&quot;Fingerprint in the circuit path is malformed (</span><span class="si">%s</span><span class="s">)&quot;</span> <span class="o">%</span> <span class="n">fingerprint</span><span class="p">)</span>

    <span class="n">fingerprint</span> <span class="o">=</span> <span class="n">fingerprint</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span>  <span class="c"># strip off the leading &#39;$&#39;</span>

  <span class="k">if</span> <span class="n">nickname</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">stem</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">tor_tools</span><span class="o">.</span><span class="n">is_valid_nickname</span><span class="p">(</span><span class="n">nickname</span><span class="p">):</span>
    <span class="k">raise</span> <span class="n">stem</span><span class="o">.</span><span class="n">ProtocolError</span><span class="p">(</span><span class="s">&quot;Nickname in the circuit path is malformed (</span><span class="si">%s</span><span class="s">)&quot;</span> <span class="o">%</span> <span class="n">nickname</span><span class="p">)</span>

  <span class="k">return</span> <span class="p">(</span><span class="n">fingerprint</span><span class="p">,</span> <span class="n">nickname</span><span class="p">)</span>


<span class="k">def</span> <span class="nf">_case_insensitive_lookup</span><span class="p">(</span><span class="n">entries</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">default</span> <span class="o">=</span> <span class="n">UNDEFINED</span><span class="p">):</span>
  <span class="sd">&quot;&quot;&quot;</span>
<span class="sd">  Makes a case insensitive lookup within a list or dictionary, providing the</span>
<span class="sd">  first matching entry that we come across.</span>

<span class="sd">  :param list,dict entries: list or dictionary to be searched</span>
<span class="sd">  :param str key: entry or key value to look up</span>
<span class="sd">  :param object default: value to be returned if the key doesn&#39;t exist</span>

<span class="sd">  :returns: case insensitive match or default if one was provided and key wasn&#39;t found</span>

<span class="sd">  :raises: **ValueError** if no such value exists</span>
<span class="sd">  &quot;&quot;&quot;</span>

  <span class="k">if</span> <span class="n">entries</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
    <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">entries</span><span class="p">,</span> <span class="nb">dict</span><span class="p">):</span>
      <span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">entries</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
        <span class="k">if</span> <span class="n">k</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="n">key</span><span class="o">.</span><span class="n">lower</span><span class="p">():</span>
          <span class="k">return</span> <span class="n">v</span>
    <span class="k">else</span><span class="p">:</span>
      <span class="k">for</span> <span class="n">entry</span> <span class="ow">in</span> <span class="n">entries</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">entry</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="n">key</span><span class="o">.</span><span class="n">lower</span><span class="p">():</span>
          <span class="k">return</span> <span class="n">entry</span>

  <span class="k">if</span> <span class="n">default</span> <span class="o">!=</span> <span class="n">UNDEFINED</span><span class="p">:</span>
    <span class="k">return</span> <span class="n">default</span>
  <span class="k">else</span><span class="p">:</span>
    <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&quot;key &#39;</span><span class="si">%s</span><span class="s">&#39; doesn&#39;t exist in dict: </span><span class="si">%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">entries</span><span class="p">))</span>
</pre></div>

      </div>
      <div class="bottomnav">
      </div>

    <div class="footer">
    </div>
  </body>
</html>