1# Copyright 2011-2019, Damian Johnson and The Tor Project
2# See LICENSE for licensing information
3
4"""
5Module for interacting with the Tor control socket. The
6:class:`~stem.control.Controller` is a wrapper around a
7:class:`~stem.socket.ControlSocket`, retaining many of its methods (connect,
8close, is_alive, etc) in addition to providing its own for working with the
9socket at a higher level.
10
11Stem has `several ways <../faq.html#how-do-i-connect-to-tor>`_ of getting a
12:class:`~stem.control.Controller`, but the most flexible are
13:func:`~stem.control.Controller.from_port` and
14:func:`~stem.control.Controller.from_socket_file`. These static
15:class:`~stem.control.Controller` methods give you an **unauthenticated**
16Controller you can then authenticate yourself using its
17:func:`~stem.control.Controller.authenticate` method. For example...
18
19::
20
21  import getpass
22  import sys
23
24  import stem
25  import stem.connection
26
27  from stem.control import Controller
28
29  if __name__ == '__main__':
30    try:
31      controller = Controller.from_port()
32    except stem.SocketError as exc:
33      print("Unable to connect to tor on port 9051: %s" % exc)
34      sys.exit(1)
35
36    try:
37      controller.authenticate()
38    except stem.connection.MissingPassword:
39      pw = getpass.getpass("Controller password: ")
40
41      try:
42        controller.authenticate(password = pw)
43      except stem.connection.PasswordAuthFailed:
44        print("Unable to authenticate, password is incorrect")
45        sys.exit(1)
46    except stem.connection.AuthenticationFailure as exc:
47      print("Unable to authenticate: %s" % exc)
48      sys.exit(1)
49
50    print("Tor is running version %s" % controller.get_version())
51    controller.close()
52
53If you're fine with allowing your script to raise exceptions then this can be more nicely done as...
54
55::
56
57  from stem.control import Controller
58
59  if __name__ == '__main__':
60    with Controller.from_port() as controller:
61      controller.authenticate()
62
63      print("Tor is running version %s" % controller.get_version())
64
65**Module Overview:**
66
67::
68
69  event_description - brief description of a tor event type
70
71  Controller - General controller class intended for direct use
72    | |- from_port - Provides a Controller based on a port connection.
73    | +- from_socket_file - Provides a Controller based on a socket file connection.
74    |
75    |- authenticate - authenticates this controller with tor
76    |- reconnect - reconnects and authenticates to socket
77    |
78    |- get_info - issues a GETINFO query for a parameter
79    |- get_version - provides our tor version
80    |- get_exit_policy - provides our exit policy
81    |- get_ports - provides the local ports where tor is listening for connections
82    |- get_listeners - provides the addresses and ports where tor is listening for connections
83    |- get_accounting_stats - provides stats related to relaying limits
84    |- get_protocolinfo - information about the controller interface
85    |- get_user - provides the user tor is running as
86    |- get_pid - provides the pid of our tor process
87    |- get_start_time - timestamp when the tor process began
88    |- get_uptime - duration tor has been running
89    |- is_user_traffic_allowed - checks if we send or receive direct user traffic
90    |
91    |- get_microdescriptor - querying the microdescriptor for a relay
92    |- get_microdescriptors - provides all currently available microdescriptors
93    |- get_server_descriptor - querying the server descriptor for a relay
94    |- get_server_descriptors - provides all currently available server descriptors
95    |- get_network_status - querying the router status entry for a relay
96    |- get_network_statuses - provides all presently available router status entries
97    |- get_hidden_service_descriptor - queries the given hidden service descriptor
98    |
99    |- get_conf - gets the value of a configuration option
100    |- get_conf_map - gets the values of multiple configuration options
101    |- is_set - determines if an option differs from its default
102    |- set_conf - sets the value of a configuration option
103    |- reset_conf - reverts configuration options to their default values
104    |- set_options - sets or resets the values of multiple configuration options
105    |
106    |- get_hidden_service_conf - provides our hidden service configuration
107    |- set_hidden_service_conf - sets our hidden service configuration
108    |- create_hidden_service - creates a new hidden service or adds a new port
109    |- remove_hidden_service - removes a hidden service or drops a port
110    |
111    |- list_ephemeral_hidden_services - list ephemeral hidden serivces
112    |- create_ephemeral_hidden_service - create a new ephemeral hidden service
113    |- remove_ephemeral_hidden_service - removes an ephemeral hidden service
114    |
115    |- add_event_listener - attaches an event listener to be notified of tor events
116    |- remove_event_listener - removes a listener so it isn't notified of further events
117    |
118    |- is_caching_enabled - true if the controller has enabled caching
119    |- set_caching - enables or disables caching
120    |- clear_cache - clears any cached results
121    |
122    |- load_conf - loads configuration information as if it was in the torrc
123    |- save_conf - saves configuration information to the torrc
124    |
125    |- is_feature_enabled - checks if a given controller feature is enabled
126    |- enable_feature - enables a controller feature that has been disabled by default
127    |
128    |- get_circuit - provides an active circuit
129    |- get_circuits - provides a list of active circuits
130    |- new_circuit - create new circuits
131    |- extend_circuit - create new circuits and extend existing ones
132    |- repurpose_circuit - change a circuit's purpose
133    |- close_circuit - close a circuit
134    |
135    |- get_streams - provides a list of active streams
136    |- attach_stream - attach a stream to a circuit
137    |- close_stream - close a stream
138    |
139    |- signal - sends a signal to the tor client
140    |- is_newnym_available - true if tor would currently accept a NEWNYM signal
141    |- get_newnym_wait - seconds until tor would accept a NEWNYM signal
142    |- get_effective_rate - provides our effective relaying rate limit
143    |- is_geoip_unavailable - true if we've discovered our geoip db to be unavailable
144    |- map_address - maps one address to another such that connections to the original are replaced with the other
145    +- drop_guards - drops our set of guard relays and picks a new set
146
147  BaseController - Base controller class asynchronous message handling
148    |- msg - communicates with the tor process
149    |- is_alive - reports if our connection to tor is open or closed
150    |- is_localhost - returns if the connection is for the local system or not
151    |- connection_time - time when we last connected or disconnected
152    |- is_authenticated - checks if we're authenticated to tor
153    |- connect - connects or reconnects to tor
154    |- close - shuts down our connection to the tor process
155    |- get_socket - provides the socket used for control communication
156    |- get_latest_heartbeat - timestamp for when we last heard from tor
157    |- add_status_listener - notifies a callback of changes in our status
158    +- remove_status_listener - prevents further notification of status changes
159
160.. data:: State (enum)
161
162  Enumeration for states that a controller can have.
163
164  ========== ===========
165  State      Description
166  ========== ===========
167  **INIT**   new control connection
168  **RESET**  received a reset/sighup signal
169  **CLOSED** control connection closed
170  ========== ===========
171
172.. data:: EventType (enum)
173
174  Known types of events that the
175  :func:`~stem.control.Controller.add_event_listener` method of the
176  :class:`~stem.control.Controller` can listen for.
177
178  The most frequently listened for event types tend to be the logging events
179  (**DEBUG**, **INFO**, **NOTICE**, **WARN**, and **ERR**), bandwidth usage
180  (**BW**), and circuit or stream changes (**CIRC** and **STREAM**).
181
182  Enums are mapped to :class:`~stem.response.events.Event` subclasses as
183  follows...
184
185  .. deprecated:: 1.6.0
186
187     Tor dropped EventType.AUTHDIR_NEWDESCS as of version 0.3.2.1.
188     (:spec:`6e887ba`)
189
190  ======================= ===========
191  EventType               Event Class
192  ======================= ===========
193  **ADDRMAP**             :class:`stem.response.events.AddrMapEvent`
194  **AUTHDIR_NEWDESCS**    :class:`stem.response.events.AuthDirNewDescEvent`
195  **BUILDTIMEOUT_SET**    :class:`stem.response.events.BuildTimeoutSetEvent`
196  **BW**                  :class:`stem.response.events.BandwidthEvent`
197  **CELL_STATS**          :class:`stem.response.events.CellStatsEvent`
198  **CIRC**                :class:`stem.response.events.CircuitEvent`
199  **CIRC_BW**             :class:`stem.response.events.CircuitBandwidthEvent`
200  **CIRC_MINOR**          :class:`stem.response.events.CircMinorEvent`
201  **CLIENTS_SEEN**        :class:`stem.response.events.ClientsSeenEvent`
202  **CONF_CHANGED**        :class:`stem.response.events.ConfChangedEvent`
203  **CONN_BW**             :class:`stem.response.events.ConnectionBandwidthEvent`
204  **DEBUG**               :class:`stem.response.events.LogEvent`
205  **DESCCHANGED**         :class:`stem.response.events.DescChangedEvent`
206  **ERR**                 :class:`stem.response.events.LogEvent`
207  **GUARD**               :class:`stem.response.events.GuardEvent`
208  **HS_DESC**             :class:`stem.response.events.HSDescEvent`
209  **HS_DESC_CONTENT**     :class:`stem.response.events.HSDescContentEvent`
210  **INFO**                :class:`stem.response.events.LogEvent`
211  **NETWORK_LIVENESS**    :class:`stem.response.events.NetworkLivenessEvent`
212  **NEWCONSENSUS**        :class:`stem.response.events.NewConsensusEvent`
213  **NEWDESC**             :class:`stem.response.events.NewDescEvent`
214  **NOTICE**              :class:`stem.response.events.LogEvent`
215  **NS**                  :class:`stem.response.events.NetworkStatusEvent`
216  **ORCONN**              :class:`stem.response.events.ORConnEvent`
217  **SIGNAL**              :class:`stem.response.events.SignalEvent`
218  **STATUS_CLIENT**       :class:`stem.response.events.StatusEvent`
219  **STATUS_GENERAL**      :class:`stem.response.events.StatusEvent`
220  **STATUS_SERVER**       :class:`stem.response.events.StatusEvent`
221  **STREAM**              :class:`stem.response.events.StreamEvent`
222  **STREAM_BW**           :class:`stem.response.events.StreamBwEvent`
223  **TB_EMPTY**            :class:`stem.response.events.TokenBucketEmptyEvent`
224  **TRANSPORT_LAUNCHED**  :class:`stem.response.events.TransportLaunchedEvent`
225  **WARN**                :class:`stem.response.events.LogEvent`
226  ======================= ===========
227
228.. data:: Listener (enum)
229
230  Purposes for inbound connections that Tor handles.
231
232  .. versionchanged:: 1.8.0
233     Added the EXTOR and HTTPTUNNEL listeners.
234
235  =============== ===========
236  Listener        Description
237  =============== ===========
238  **OR**          traffic we're relaying as a member of the network (torrc's **ORPort** and **ORListenAddress**)
239  **DIR**         mirroring for tor descriptor content (torrc's **DirPort** and **DirListenAddress**)
240  **SOCKS**       client traffic we're sending over Tor (torrc's **SocksPort** and **SocksListenAddress**)
241  **TRANS**       transparent proxy handling (torrc's **TransPort** and **TransListenAddress**)
242  **NATD**        forwarding for ipfw NATD connections (torrc's **NatdPort** and **NatdListenAddress**)
243  **DNS**         DNS lookups for our traffic (torrc's **DNSPort** and **DNSListenAddress**)
244  **CONTROL**     controller applications (torrc's **ControlPort** and **ControlListenAddress**)
245  **EXTOR**       pluggable transport for Extended ORPorts (torrc's **ExtORPort**)
246  **HTTPTUNNEL**  http tunneling proxy (torrc's **HTTPTunnelPort**)
247  =============== ===========
248"""
249
250import calendar
251import collections
252import functools
253import inspect
254import io
255import os
256import threading
257import time
258
259try:
260  # Added in 2.7
261  from collections import OrderedDict
262except ImportError:
263  from stem.util.ordereddict import OrderedDict
264
265try:
266  # Added in 3.x
267  import queue
268except ImportError:
269  import Queue as queue
270
271import stem.descriptor.microdescriptor
272import stem.descriptor.reader
273import stem.descriptor.router_status_entry
274import stem.descriptor.server_descriptor
275import stem.exit_policy
276import stem.response
277import stem.response.events
278import stem.socket
279import stem.util
280import stem.util.conf
281import stem.util.connection
282import stem.util.enum
283import stem.util.str_tools
284import stem.util.system
285import stem.util.tor_tools
286import stem.version
287
288from stem import UNDEFINED, CircStatus, Signal
289from stem.util import log
290
291# When closing the controller we attempt to finish processing enqueued events,
292# but if it takes longer than this we terminate.
293
294EVENTS_LISTENING_TIMEOUT = 0.1
295
296MALFORMED_EVENTS = 'MALFORMED_EVENTS'
297
298# state changes a control socket can have
299
300State = stem.util.enum.Enum('INIT', 'RESET', 'CLOSED')
301
302# TODO: consider merging this with stem.response.event in stem 2.x? (#32689)
303
304EventType = stem.util.enum.UppercaseEnum(
305  'ADDRMAP',
306  'AUTHDIR_NEWDESCS',
307  'BUILDTIMEOUT_SET',
308  'BW',
309  'CELL_STATS',
310  'CIRC',
311  'CIRC_BW',
312  'CIRC_MINOR',
313  'CONF_CHANGED',
314  'CONN_BW',
315  'CLIENTS_SEEN',
316  'DEBUG',
317  'DESCCHANGED',
318  'ERR',
319  'GUARD',
320  'HS_DESC',
321  'HS_DESC_CONTENT',
322  'INFO',
323  'NETWORK_LIVENESS',
324  'NEWCONSENSUS',
325  'NEWDESC',
326  'NOTICE',
327  'NS',
328  'ORCONN',
329  'SIGNAL',
330  'STATUS_CLIENT',
331  'STATUS_GENERAL',
332  'STATUS_SERVER',
333  'STREAM',
334  'STREAM_BW',
335  'TB_EMPTY',
336  'TRANSPORT_LAUNCHED',
337  'WARN',
338)
339
340Listener = stem.util.enum.UppercaseEnum(
341  'OR',
342  'DIR',
343  'SOCKS',
344  'TRANS',
345  'NATD',
346  'DNS',
347  'CONTROL',
348  'EXTOR',
349  'HTTPTUNNEL',
350)
351
352# torrc options that cannot be changed once tor's running
353
354IMMUTABLE_CONFIG_OPTIONS = set(map(stem.util.str_tools._to_unicode, map(str.lower, (
355  'AccelDir',
356  'AccelName',
357  'DataDirectory',
358  'DisableAllSwap',
359  'DisableDebuggerAttachment',
360  'HardwareAccel',
361  'HiddenServiceNonAnonymousMode',
362  'HiddenServiceSingleHopMode',
363  'KeepBindCapabilities',
364  'PidFile',
365  'RunAsDaemon',
366  'Sandbox',
367  'SyslogIdentityTag',
368  'TokenBucketRefillInterval',
369  'User',
370))))
371
372LOG_CACHE_FETCHES = True  # provide trace level logging for cache hits
373
374# Configuration options that are fetched by a special key. The keys are
375# lowercase to make case insensitive lookups easier.
376
377MAPPED_CONFIG_KEYS = {
378  'hiddenservicedir': 'HiddenServiceOptions',
379  'hiddenserviceport': 'HiddenServiceOptions',
380  'hiddenserviceversion': 'HiddenServiceOptions',
381  'hiddenserviceauthorizeclient': 'HiddenServiceOptions',
382  'hiddenserviceoptions': 'HiddenServiceOptions',
383}
384
385# unchangeable GETINFO parameters
386
387CACHEABLE_GETINFO_PARAMS = (
388  'address',
389  'version',
390  'config-file',
391  'exit-policy/default',
392  'fingerprint',
393  'config/names',
394  'config/defaults',
395  'info/names',
396  'events/names',
397  'features/names',
398  'process/descriptor-limit',
399  'status/version/current',
400)
401
402CACHEABLE_GETINFO_PARAMS_UNTIL_SETCONF = (
403  'accounting/enabled',
404)
405
406# GETCONF parameters we shouldn't cache. This includes hidden service
407# perameters due to the funky way they're set and retrieved (for instance,
408# 'SETCONF HiddenServiceDir' effects 'GETCONF HiddenServiceOptions').
409
410UNCACHEABLE_GETCONF_PARAMS = (
411  'hiddenserviceoptions',
412  'hiddenservicedir',
413  'hiddenserviceport',
414  'hiddenserviceversion',
415  'hiddenserviceauthorizeclient',
416)
417
418SERVER_DESCRIPTORS_UNSUPPORTED = "Tor is currently not configured to retrieve \
419server descriptors. As of Tor version 0.2.3.25 it downloads microdescriptors \
420instead unless you set 'UseMicrodescriptors 0' in your torrc."
421
422EVENT_DESCRIPTIONS = None
423
424
425class AccountingStats(collections.namedtuple('AccountingStats', ['retrieved', 'status', 'interval_end', 'time_until_reset', 'read_bytes', 'read_bytes_left', 'read_limit', 'written_bytes', 'write_bytes_left', 'write_limit'])):
426  """
427  Accounting information, determining the limits where our relay suspends
428  itself.
429
430  :var float retrieved: unix timestamp for when this was fetched
431  :var str status: hibernation status of 'awake', 'soft', or 'hard'
432  :var datetime interval_end: time when our limits reset
433  :var int time_until_reset: seconds until our limits reset
434  :var int read_bytes: number of bytes we've read relaying
435  :var int read_bytes_left: number of bytes we can read until we suspend
436  :var int read_limit: reading threshold where we suspend
437  :var int written_bytes: number of bytes we've written relaying
438  :var int write_bytes_left: number of bytes we can write until we suspend
439  :var int write_limit: writing threshold where we suspend
440  """
441
442
443class UserTrafficAllowed(collections.namedtuple('UserTrafficAllowed', ['inbound', 'outbound'])):
444  """
445  Indicates if we're likely to be servicing direct user traffic or not.
446
447  :var bool inbound: if **True** we're likely providing guard or bridge connnections
448  :var bool outbound: if **True** we're likely providng exit connections
449  """
450
451
452class CreateHiddenServiceOutput(collections.namedtuple('CreateHiddenServiceOutput', ['path', 'hostname', 'hostname_for_client', 'config'])):
453  """
454  Attributes of a hidden service we've created.
455
456  Both the **hostnames** and **hostname_for_client** attributes can only be
457  provided if we're able to read the hidden service directory. If the method
458  was called with **client_names** then we may provide the
459  **hostname_for_client**, and otherwise can provide the **hostnames**.
460
461  :var str path: hidden service directory
462  :var str hostname: content of the hostname file if available
463  :var dict hostname_for_client: mapping of client names to their onion address
464    if available
465  :var dict config: tor's new hidden service configuration
466  """
467
468
469def with_default(yields = False):
470  """
471  Provides a decorator to support having a default value. This should be
472  treated as private.
473  """
474
475  def decorator(func):
476    def get_default(func, args, kwargs):
477      arg_names = inspect.getargspec(func).args[1:]  # drop 'self'
478      default_position = arg_names.index('default') if 'default' in arg_names else None
479
480      if default_position is not None and default_position < len(args):
481        return args[default_position]
482      else:
483        return kwargs.get('default', UNDEFINED)
484
485    if not yields:
486      @functools.wraps(func)
487      def wrapped(self, *args, **kwargs):
488        try:
489          return func(self, *args, **kwargs)
490        except:
491          default = get_default(func, args, kwargs)
492
493          if default == UNDEFINED:
494            raise
495          else:
496            return default
497    else:
498      @functools.wraps(func)
499      def wrapped(self, *args, **kwargs):
500        try:
501          for val in func(self, *args, **kwargs):
502            yield val
503        except:
504          default = get_default(func, args, kwargs)
505
506          if default == UNDEFINED:
507            raise
508          else:
509            if default is not None:
510              for val in default:
511                yield val
512
513    return wrapped
514
515  return decorator
516
517
518def event_description(event):
519  """
520  Provides a description for Tor events.
521
522  :param str event: the event for which a description is needed
523
524  :returns: **str** The event description or **None** if this is an event name
525    we don't have a description for
526  """
527
528  global EVENT_DESCRIPTIONS
529
530  if EVENT_DESCRIPTIONS is None:
531    config = stem.util.conf.Config()
532    config_path = os.path.join(os.path.dirname(__file__), 'settings.cfg')
533
534    try:
535      config.load(config_path)
536      EVENT_DESCRIPTIONS = dict([(key.lower()[18:], config.get_value(key)) for key in config.keys() if key.startswith('event.description.')])
537    except Exception as exc:
538      log.warn("BUG: stem failed to load its internal manual information from '%s': %s" % (config_path, exc))
539      return None
540
541  return EVENT_DESCRIPTIONS.get(event.lower())
542
543
544class BaseController(object):
545  """
546  Controller for the tor process. This is a minimal base class for other
547  controllers, providing basic process communication and event listing. Don't
548  use this directly - subclasses like the :class:`~stem.control.Controller`
549  provide higher level functionality.
550
551  It's highly suggested that you don't interact directly with the
552  :class:`~stem.socket.ControlSocket` that we're constructed from - use our
553  wrapper methods instead.
554
555  If the **control_socket** is already authenticated to Tor then the caller
556  should provide the **is_authenticated** flag. Otherwise, we will treat the
557  socket as though it hasn't yet been authenticated.
558  """
559
560  def __init__(self, control_socket, is_authenticated = False):
561    self._socket = control_socket
562    self._msg_lock = threading.RLock()
563
564    self._status_listeners = []  # tuples of the form (callback, spawn_thread)
565    self._status_listeners_lock = threading.RLock()
566
567    # queues where incoming messages are directed
568    self._reply_queue = queue.Queue()
569    self._event_queue = queue.Queue()
570
571    # thread to continually pull from the control socket
572    self._reader_thread = None
573
574    # thread to pull from the _event_queue and call handle_event
575    self._event_notice = threading.Event()
576    self._event_thread = None
577
578    # saves our socket's prior _connect() and _close() methods so they can be
579    # called along with ours
580
581    self._socket_connect = self._socket._connect
582    self._socket_close = self._socket._close
583
584    self._socket._connect = self._connect
585    self._socket._close = self._close
586
587    self._last_heartbeat = 0.0  # timestamp for when we last heard from tor
588    self._is_authenticated = False
589
590    self._state_change_threads = []  # threads we've spawned to notify of state changes
591
592    if self._socket.is_alive():
593      self._launch_threads()
594
595    if is_authenticated:
596      self._post_authentication()
597
598  def msg(self, message):
599    """
600    Sends a message to our control socket and provides back its reply.
601
602    :param str message: message to be formatted and sent to tor
603
604    :returns: :class:`~stem.response.ControlMessage` with the response
605
606    :raises:
607      * :class:`stem.ProtocolError` the content from the socket is
608        malformed
609      * :class:`stem.SocketError` if a problem arises in using the
610        socket
611      * :class:`stem.SocketClosed` if the socket is shut down
612    """
613
614    with self._msg_lock:
615      # If our _reply_queue isn't empty then one of a few things happened...
616      #
617      # - Our connection was closed and probably re-restablished. This was
618      #   in reply to pulling for an asynchronous event and getting this is
619      #   expected - ignore it.
620      #
621      # - Pulling for asynchronous events produced an error. If this was a
622      #   ProtocolError then it's a tor bug, and if a non-closure SocketError
623      #   then it was probably a socket glitch. Deserves an INFO level log
624      #   message.
625      #
626      # - This is a leftover response for a msg() call. We can't tell who an
627      #   exception was earmarked for, so we only know that this was the case
628      #   if it's a ControlMessage.
629      #
630      #   This is the most concerning situation since it indicates that one of
631      #   our callers didn't get their reply. However, this is still a
632      #   perfectly viable use case. For instance...
633      #
634      #   1. We send a request.
635      #   2. The reader thread encounters an exception, for instance a socket
636      #      error. We enqueue the exception.
637      #   3. The reader thread receives the reply.
638      #   4. We raise the socket error, and have an undelivered message.
639      #
640      #   Thankfully this only seems to arise in edge cases around rapidly
641      #   closing/reconnecting the socket.
642
643      while not self._reply_queue.empty():
644        try:
645          response = self._reply_queue.get_nowait()
646
647          if isinstance(response, stem.SocketClosed):
648            pass  # this is fine
649          elif isinstance(response, stem.ProtocolError):
650            log.info('Tor provided a malformed message (%s)' % response)
651          elif isinstance(response, stem.ControllerError):
652            log.info('Socket experienced a problem (%s)' % response)
653          elif isinstance(response, stem.response.ControlMessage):
654            log.info('Failed to deliver a response: %s' % response)
655        except queue.Empty:
656          # the empty() method is documented to not be fully reliable so this
657          # isn't entirely surprising
658
659          break
660
661      try:
662        self._socket.send(message)
663        response = self._reply_queue.get()
664
665        # If the message we received back had an exception then re-raise it to the
666        # caller. Otherwise return the response.
667
668        if isinstance(response, stem.ControllerError):
669          raise response
670        else:
671          return response
672      except stem.SocketClosed:
673        # If the recv() thread caused the SocketClosed then we could still be
674        # in the process of closing. Calling close() here so that we can
675        # provide an assurance to the caller that when we raise a SocketClosed
676        # exception we are shut down afterward for realz.
677
678        self.close()
679        raise
680
681  def is_alive(self):
682    """
683    Checks if our socket is currently connected. This is a pass-through for our
684    socket's :func:`~stem.socket.BaseSocket.is_alive` method.
685
686    :returns: **bool** that's **True** if our socket is connected and **False** otherwise
687    """
688
689    return self._socket.is_alive()
690
691  def is_localhost(self):
692    """
693    Returns if the connection is for the local system or not.
694
695    .. versionadded:: 1.3.0
696
697    :returns: **bool** that's **True** if the connection is for the local host and **False** otherwise
698    """
699
700    return self._socket.is_localhost()
701
702  def connection_time(self):
703    """
704    Provides the unix timestamp for when our socket was either connected or
705    disconnected. That is to say, the time we connected if we're currently
706    connected and the time we disconnected if we're not connected.
707
708    .. versionadded:: 1.3.0
709
710    :returns: **float** for when we last connected or disconnected, zero if
711      we've never connected
712    """
713
714    return self._socket.connection_time()
715
716  def is_authenticated(self):
717    """
718    Checks if our socket is both connected and authenticated.
719
720    :returns: **bool** that's **True** if our socket is authenticated to tor
721      and **False** otherwise
722    """
723
724    return self._is_authenticated if self.is_alive() else False
725
726  def connect(self):
727    """
728    Reconnects our control socket. This is a pass-through for our socket's
729    :func:`~stem.socket.ControlSocket.connect` method.
730
731    :raises: :class:`stem.SocketError` if unable to make a socket
732    """
733
734    self._socket.connect()
735
736  def close(self):
737    """
738    Closes our socket connection. This is a pass-through for our socket's
739    :func:`~stem.socket.BaseSocket.close` method.
740    """
741
742    self._socket.close()
743
744    # Join on any outstanding state change listeners. Closing is a state change
745    # of its own, so if we have any listeners it's quite likely there's some
746    # work in progress.
747    #
748    # It's important that we do this outside of our locks so those daemons have
749    # access to us. This is why we're doing this here rather than _close().
750
751    for t in self._state_change_threads:
752      if t.is_alive() and threading.current_thread() != t:
753        t.join()
754
755  def get_socket(self):
756    """
757    Provides the socket used to speak with the tor process. Communicating with
758    the socket directly isn't advised since it may confuse this controller.
759
760    :returns: :class:`~stem.socket.ControlSocket` we're communicating with
761    """
762
763    return self._socket
764
765  def get_latest_heartbeat(self):
766    """
767    Provides the unix timestamp for when we last heard from tor. This is zero
768    if we've never received a message.
769
770    :returns: float for the unix timestamp of when we last heard from tor
771    """
772
773    return self._last_heartbeat
774
775  def add_status_listener(self, callback, spawn = True):
776    """
777    Notifies a given function when the state of our socket changes. Functions
778    are expected to be of the form...
779
780    ::
781
782      my_function(controller, state, timestamp)
783
784    The state is a value from the :data:`stem.control.State` enum. Functions
785    **must** allow for new values. The timestamp is a float for the unix time
786    when the change occurred.
787
788    This class only provides **State.INIT** and **State.CLOSED** notifications.
789    Subclasses may provide others.
790
791    If spawn is **True** then the callback is notified via a new daemon thread.
792    If **False** then the notice is under our locks, within the thread where
793    the change occurred. In general this isn't advised, especially if your
794    callback could block for a while. If still outstanding these threads are
795    joined on as part of closing this controller.
796
797    :param function callback: function to be notified when our state changes
798    :param bool spawn: calls function via a new thread if **True**, otherwise
799      it's part of the connect/close method call
800    """
801
802    with self._status_listeners_lock:
803      self._status_listeners.append((callback, spawn))
804
805  def remove_status_listener(self, callback):
806    """
807    Stops listener from being notified of further events.
808
809    :param function callback: function to be removed from our listeners
810
811    :returns: **bool** that's **True** if we removed one or more occurrences of
812      the callback, **False** otherwise
813    """
814
815    with self._status_listeners_lock:
816      new_listeners, is_changed = [], False
817
818      for listener, spawn in self._status_listeners:
819        if listener != callback:
820          new_listeners.append((listener, spawn))
821        else:
822          is_changed = True
823
824      self._status_listeners = new_listeners
825      return is_changed
826
827  def __enter__(self):
828    return self
829
830  def __exit__(self, exit_type, value, traceback):
831    self.close()
832
833  def _handle_event(self, event_message):
834    """
835    Callback to be overwritten by subclasses for event listening. This is
836    notified whenever we receive an event from the control socket.
837
838    :param stem.response.ControlMessage event_message: message received from
839      the control socket
840    """
841
842    pass
843
844  def _connect(self):
845    self._launch_threads()
846    self._notify_status_listeners(State.INIT)
847    self._socket_connect()
848    self._is_authenticated = False
849
850  def _close(self):
851    # Our is_alive() state is now false. Our reader thread should already be
852    # awake from recv() raising a closure exception. Wake up the event thread
853    # too so it can end.
854
855    self._event_notice.set()
856    self._is_authenticated = False
857
858    # joins on our threads if it's safe to do so
859
860    for t in (self._reader_thread, self._event_thread):
861      if t and t.is_alive() and threading.current_thread() != t:
862        t.join()
863
864    self._notify_status_listeners(State.CLOSED)
865
866    self._socket_close()
867
868  def _post_authentication(self):
869    # actions to be taken after we have a newly authenticated connection
870
871    self._is_authenticated = True
872
873  def _notify_status_listeners(self, state):
874    """
875    Informs our status listeners that a state change occurred.
876
877    :param stem.control.State state: state change that has occurred
878    """
879
880    # Any changes to our is_alive() state happen under the send lock, so we
881    # need to have it to ensure it doesn't change beneath us.
882
883    with self._socket._get_send_lock():
884      with self._status_listeners_lock:
885        # States imply that our socket is either alive or not, which may not
886        # hold true when multiple events occur in quick succession. For
887        # instance, a sighup could cause two events (State.RESET for the sighup
888        # and State.CLOSE if it causes tor to crash). However, there's no
889        # guarantee of the order in which they occur, and it would be bad if
890        # listeners got the State.RESET last, implying that we were alive.
891
892        expect_alive = None
893
894        if state in (State.INIT, State.RESET):
895          expect_alive = True
896        elif state == State.CLOSED:
897          expect_alive = False
898
899        change_timestamp = time.time()
900
901        if expect_alive is not None and expect_alive != self.is_alive():
902          return
903
904        self._state_change_threads = list(filter(lambda t: t.is_alive(), self._state_change_threads))
905
906        for listener, spawn in self._status_listeners:
907          if spawn:
908            args = (self, state, change_timestamp)
909
910            notice_thread = threading.Thread(target = listener, args = args, name = '%s notification' % state)
911            notice_thread.setDaemon(True)
912            notice_thread.start()
913            self._state_change_threads.append(notice_thread)
914          else:
915            listener(self, state, change_timestamp)
916
917  def _launch_threads(self):
918    """
919    Initializes daemon threads. Threads can't be reused so we need to recreate
920    them if we're restarted.
921    """
922
923    # In theory concurrent calls could result in multiple start() calls on a
924    # single thread, which would cause an unexpected exception. Best be safe.
925
926    with self._socket._get_send_lock():
927      if not self._reader_thread or not self._reader_thread.is_alive():
928        self._reader_thread = threading.Thread(target = self._reader_loop, name = 'Tor listener')
929        self._reader_thread.setDaemon(True)
930        self._reader_thread.start()
931
932      if not self._event_thread or not self._event_thread.is_alive():
933        self._event_thread = threading.Thread(target = self._event_loop, name = 'Event notifier')
934        self._event_thread.setDaemon(True)
935        self._event_thread.start()
936
937  def _reader_loop(self):
938    """
939    Continually pulls from the control socket, directing the messages into
940    queues based on their type. Controller messages come in two varieties...
941
942    * Responses to messages we've sent (GETINFO, SETCONF, etc).
943    * Asynchronous events, identified by a status code of 650.
944    """
945
946    while self.is_alive():
947      try:
948        control_message = self._socket.recv()
949        self._last_heartbeat = time.time()
950
951        if control_message.content()[-1][0] == '650':
952          # asynchronous message, adds to the event queue and wakes up its handler
953          self._event_queue.put(control_message)
954          self._event_notice.set()
955        else:
956          # response to a msg() call
957          self._reply_queue.put(control_message)
958      except stem.ControllerError as exc:
959        # Assume that all exceptions belong to the reader. This isn't always
960        # true, but the msg() call can do a better job of sorting it out.
961        #
962        # Be aware that the msg() method relies on this to unblock callers.
963
964        self._reply_queue.put(exc)
965
966  def _event_loop(self):
967    """
968    Continually pulls messages from the _event_queue and sends them to our
969    handle_event callback. This is done via its own thread so subclasses with a
970    lengthy handle_event implementation don't block further reading from the
971    socket.
972    """
973
974    socket_closed_at = None
975
976    while True:
977      try:
978        event_message = self._event_queue.get_nowait()
979        self._handle_event(event_message)
980        self._event_queue.task_done()
981
982        # Attempt to finish processing enqueued events when our controller closes
983
984        if not self.is_alive():
985          if not socket_closed_at:
986            socket_closed_at = time.time()
987          elif time.time() - socket_closed_at > EVENTS_LISTENING_TIMEOUT:
988            break
989      except queue.Empty:
990        if not self.is_alive():
991          break
992
993        self._event_notice.wait(0.05)
994        self._event_notice.clear()
995
996
997class Controller(BaseController):
998  """
999  Connection with Tor's control socket. This is built on top of the
1000  BaseController and provides a more user friendly API for library users.
1001  """
1002
1003  @staticmethod
1004  def from_port(address = '127.0.0.1', port = 'default'):
1005    """
1006    Constructs a :class:`~stem.socket.ControlPort` based Controller.
1007
1008    If the **port** is **'default'** then this checks on both 9051 (default
1009    for relays) and 9151 (default for the Tor Browser). This default may change
1010    in the future.
1011
1012    .. versionchanged:: 1.5.0
1013       Use both port 9051 and 9151 by default.
1014
1015    :param str address: ip address of the controller
1016    :param int port: port number of the controller
1017
1018    :returns: :class:`~stem.control.Controller` attached to the given port
1019
1020    :raises: :class:`stem.SocketError` if we're unable to establish a connection
1021    """
1022
1023    import stem.connection
1024
1025    if not stem.util.connection.is_valid_ipv4_address(address):
1026      raise ValueError('Invalid IP address: %s' % address)
1027    elif port != 'default' and not stem.util.connection.is_valid_port(port):
1028      raise ValueError('Invalid port: %s' % port)
1029
1030    if port == 'default':
1031      control_port = stem.connection._connection_for_default_port(address)
1032    else:
1033      control_port = stem.socket.ControlPort(address, port)
1034
1035    return Controller(control_port)
1036
1037  @staticmethod
1038  def from_socket_file(path = '/var/run/tor/control'):
1039    """
1040    Constructs a :class:`~stem.socket.ControlSocketFile` based Controller.
1041
1042    :param str path: path where the control socket is located
1043
1044    :returns: :class:`~stem.control.Controller` attached to the given socket file
1045
1046    :raises: :class:`stem.SocketError` if we're unable to establish a connection
1047    """
1048
1049    control_socket = stem.socket.ControlSocketFile(path)
1050    return Controller(control_socket)
1051
1052  def __init__(self, control_socket, is_authenticated = False):
1053    self._is_caching_enabled = True
1054    self._request_cache = {}
1055    self._last_newnym = 0.0
1056
1057    self._cache_lock = threading.RLock()
1058
1059    # mapping of event types to their listeners
1060
1061    self._event_listeners = {}
1062    self._event_listeners_lock = threading.RLock()
1063    self._enabled_features = []
1064    self._is_geoip_unavailable = None
1065
1066    self._last_address_exc = None
1067    self._last_fingerprint_exc = None
1068
1069    super(Controller, self).__init__(control_socket, is_authenticated)
1070
1071    def _sighup_listener(event):
1072      if event.signal == Signal.RELOAD:
1073        self.clear_cache()
1074        self._notify_status_listeners(State.RESET)
1075
1076    self.add_event_listener(_sighup_listener, EventType.SIGNAL)
1077
1078    def _confchanged_listener(event):
1079      if self.is_caching_enabled():
1080        to_cache_changed = dict((k.lower(), v) for k, v in event.changed.items())
1081        to_cache_unset = dict((k.lower(), []) for k in event.unset)  # [] represents None value in cache
1082
1083        to_cache = {}
1084        to_cache.update(to_cache_changed)
1085        to_cache.update(to_cache_unset)
1086
1087        self._set_cache(to_cache, 'getconf')
1088
1089        self._confchanged_cache_invalidation(to_cache)
1090
1091    self.add_event_listener(_confchanged_listener, EventType.CONF_CHANGED)
1092
1093    def _address_changed_listener(event):
1094      if event.action in ('EXTERNAL_ADDRESS', 'DNS_USELESS'):
1095        self._set_cache({'exit_policy': None})
1096        self._set_cache({'address': None}, 'getinfo')
1097        self._last_address_exc = None
1098
1099    self.add_event_listener(_address_changed_listener, EventType.STATUS_SERVER)
1100
1101  def close(self):
1102    self.clear_cache()
1103    super(Controller, self).close()
1104
1105  def authenticate(self, *args, **kwargs):
1106    """
1107    A convenience method to authenticate the controller. This is just a
1108    pass-through to :func:`stem.connection.authenticate`.
1109    """
1110
1111    import stem.connection
1112    stem.connection.authenticate(self, *args, **kwargs)
1113
1114  def reconnect(self, *args, **kwargs):
1115    """
1116    Reconnects and authenticates to our control socket.
1117
1118    .. versionadded:: 1.5.0
1119
1120    :raises:
1121      * :class:`stem.SocketError` if unable to re-establish socket
1122      * :class:`stem.connection.AuthenticationFailure` if unable to authenticate
1123    """
1124
1125    with self._msg_lock:
1126      self.connect()
1127      self.clear_cache()
1128      self.authenticate(*args, **kwargs)
1129
1130  @with_default()
1131  def get_info(self, params, default = UNDEFINED, get_bytes = False):
1132    """
1133    get_info(params, default = UNDEFINED, get_bytes = False)
1134
1135    Queries the control socket for the given GETINFO option. If provided a
1136    default then that's returned if the GETINFO option is undefined or the
1137    call fails for any reason (error response, control port closed, initiated,
1138    etc).
1139
1140    .. versionchanged:: 1.1.0
1141       Added the get_bytes argument.
1142
1143    .. versionchanged:: 1.7.0
1144       Errors commonly provided a :class:`stem.ProtocolError` when we should
1145       raise a :class:`stem.OperationFailed`.
1146
1147    :param str,list params: GETINFO option or options to be queried
1148    :param object default: response if the query fails
1149    :param bool get_bytes: provides **bytes** values rather than a **str** under python 3.x
1150
1151    :returns:
1152      Response depends upon how we were called as follows...
1153
1154      * **str** with the response if our param was a **str**
1155      * **dict** with the 'param => response' mapping if our param was a **list**
1156      * default if one was provided and our call failed
1157
1158    :raises:
1159      * :class:`stem.ControllerError` if the call fails and we weren't
1160        provided a default response
1161      * :class:`stem.InvalidArguments` if the 'params' requested was
1162        invalid
1163      * :class:`stem.ProtocolError` if the geoip database is unavailable
1164    """
1165
1166    start_time = time.time()
1167    reply = {}
1168
1169    if stem.util._is_str(params):
1170      is_multiple = False
1171      params = set([params])
1172    else:
1173      if not params:
1174        return {}
1175
1176      is_multiple = True
1177      params = set(params)
1178
1179    for param in params:
1180      if param.startswith('ip-to-country/') and param != 'ip-to-country/0.0.0.0' and self.is_geoip_unavailable():
1181        raise stem.ProtocolError('Tor geoip database is unavailable')
1182      elif param == 'address' and self._last_address_exc:
1183        raise self._last_address_exc  # we already know we can't resolve an address
1184      elif param == 'fingerprint' and self._last_fingerprint_exc and self.get_conf('ORPort', None) is None:
1185        raise self._last_fingerprint_exc  # we already know we're not a relay
1186
1187    # check for cached results
1188
1189    from_cache = [param.lower() for param in params]
1190    cached_results = self._get_cache_map(from_cache, 'getinfo')
1191
1192    for key in cached_results:
1193      user_expected_key = _case_insensitive_lookup(params, key)
1194      reply[user_expected_key] = cached_results[key]
1195      params.remove(user_expected_key)
1196
1197    # if everything was cached then short circuit making the query
1198    if not params:
1199      if LOG_CACHE_FETCHES:
1200        log.trace('GETINFO %s (cache fetch)' % ' '.join(reply.keys()))
1201
1202      if is_multiple:
1203        return reply
1204      else:
1205        return list(reply.values())[0]
1206
1207    try:
1208      response = self.msg('GETINFO %s' % ' '.join(params))
1209      stem.response.convert('GETINFO', response)
1210      response._assert_matches(params)
1211
1212      # usually we want unicode values under python 3.x
1213
1214      if stem.prereq.is_python_3() and not get_bytes:
1215        response.entries = dict((k, stem.util.str_tools._to_unicode(v)) for (k, v) in response.entries.items())
1216
1217      reply.update(response.entries)
1218
1219      if self.is_caching_enabled():
1220        to_cache = {}
1221
1222        for key, value in response.entries.items():
1223          key = key.lower()  # make case insensitive
1224
1225          if key in CACHEABLE_GETINFO_PARAMS or key in CACHEABLE_GETINFO_PARAMS_UNTIL_SETCONF:
1226            to_cache[key] = value
1227          elif key.startswith('ip-to-country/'):
1228            to_cache[key] = value
1229
1230        self._set_cache(to_cache, 'getinfo')
1231
1232      if 'address' in params:
1233        self._last_address_exc = None
1234
1235      if 'fingerprint' in params:
1236        self._last_fingerprint_exc = None
1237
1238      log.debug('GETINFO %s (runtime: %0.4f)' % (' '.join(params), time.time() - start_time))
1239
1240      if is_multiple:
1241        return reply
1242      else:
1243        return list(reply.values())[0]
1244    except stem.ControllerError as exc:
1245      if 'address' in params:
1246        self._last_address_exc = exc
1247
1248      if 'fingerprint' in params:
1249        self._last_fingerprint_exc = exc
1250
1251      log.debug('GETINFO %s (failed: %s)' % (' '.join(params), exc))
1252      raise
1253
1254  @with_default()
1255  def get_version(self, default = UNDEFINED):
1256    """
1257    get_version(default = UNDEFINED)
1258
1259    A convenience method to get tor version that current controller is
1260    connected to.
1261
1262    :param object default: response if the query fails
1263
1264    :returns: :class:`~stem.version.Version` of the tor instance that we're
1265      connected to
1266
1267    :raises:
1268      * :class:`stem.ControllerError` if unable to query the version
1269      * **ValueError** if unable to parse the version
1270
1271      An exception is only raised if we weren't provided a default response.
1272    """
1273
1274    version = self._get_cache('version')
1275
1276    if not version:
1277      version_str = self.get_info('version')
1278      version = stem.version.Version(version_str[4:] if version_str.startswith('Tor ') else version_str)
1279      self._set_cache({'version': version})
1280
1281    return version
1282
1283  @with_default()
1284  def get_exit_policy(self, default = UNDEFINED):
1285    """
1286    get_exit_policy(default = UNDEFINED)
1287
1288    Effective ExitPolicy for our relay.
1289
1290    .. versionchanged:: 1.7.0
1291       Policies retrieved through 'GETINFO exit-policy/full' rather than
1292       parsing the user's torrc entries. This should be more reliable for
1293       some edge cases. (:trac:`25739`)
1294
1295    :param object default: response if the query fails
1296
1297    :returns: :class:`~stem.exit_policy.ExitPolicy` of the tor instance that
1298      we're connected to
1299
1300    :raises:
1301      * :class:`stem.ControllerError` if unable to query the policy
1302      * **ValueError** if unable to parse the policy
1303
1304      An exception is only raised if we weren't provided a default response.
1305    """
1306
1307    policy = self._get_cache('exit_policy')
1308
1309    if not policy:
1310      try:
1311        policy = stem.exit_policy.ExitPolicy(*self.get_info('exit-policy/full').splitlines())
1312        self._set_cache({'exit_policy': policy})
1313      except stem.OperationFailed:
1314        # There's a few situations where 'GETINFO exit-policy/full' will fail,
1315        # most commonly...
1316        #
1317        #   * Error 551: Descriptor still rebuilding - not ready yet
1318        #
1319        #     Tor hasn't yet finished making our server descriptor. This often
1320        #     arises when tor has first started.
1321        #
1322        #   * Error 552: Not running in server mode
1323        #
1324        #     We're not configured to be a relay (no ORPort), or haven't yet
1325        #     been able to determine our externally facing IP address.
1326        #
1327        # When these arise best we can do is infer our policy from the torrc.
1328        # Skipping caching so we'll retry GETINFO policy resolution next time
1329        # we're called.
1330
1331        rules = []
1332
1333        if self.get_conf('ExitRelay') == '0':
1334          rules.append('reject *:*')
1335
1336        if self.get_conf('ExitPolicyRejectPrivate') == '1':
1337          rules.append('reject private:*')
1338
1339        for policy_line in self.get_conf('ExitPolicy', multiple = True):
1340          rules += policy_line.split(',')
1341
1342        rules += self.get_info('exit-policy/default').split(',')
1343
1344        policy = stem.exit_policy.get_config_policy(rules, self.get_info('address', None))
1345
1346    return policy
1347
1348  @with_default()
1349  def get_ports(self, listener_type, default = UNDEFINED):
1350    """
1351    get_ports(listener_type, default = UNDEFINED)
1352
1353    Provides the local ports where tor is listening for the given type of
1354    connections. This is similar to
1355    :func:`~stem.control.Controller.get_listeners`, but doesn't provide
1356    addresses nor include non-local endpoints.
1357
1358    .. versionadded:: 1.2.0
1359
1360    :param stem.control.Listener listener_type: connection type being handled
1361      by the ports we return
1362    :param object default: response if the query fails
1363
1364    :returns: **list** of **ints** for the local ports where tor handles
1365      connections of the given type
1366
1367    :raises: :class:`stem.ControllerError` if unable to determine the ports
1368      and no default was provided
1369    """
1370
1371    def is_localhost(address):
1372      if stem.util.connection.is_valid_ipv4_address(address):
1373        return address == '0.0.0.0' or address.startswith('127.')
1374      elif stem.util.connection.is_valid_ipv6_address(address):
1375        return stem.util.connection.expand_ipv6_address(address) in (
1376          '0000:0000:0000:0000:0000:0000:0000:0000',
1377          '0000:0000:0000:0000:0000:0000:0000:0001',
1378        )
1379      else:
1380        log.info("Request for %s ports got an address that's neither IPv4 or IPv6: %s" % (listener_type, address))
1381        return False
1382
1383    return [port for (addr, port) in self.get_listeners(listener_type) if is_localhost(addr)]
1384
1385  @with_default()
1386  def get_listeners(self, listener_type, default = UNDEFINED):
1387    """
1388    get_listeners(listener_type, default = UNDEFINED)
1389
1390    Provides the addresses and ports where tor is listening for connections of
1391    the given type. This is similar to
1392    :func:`~stem.control.Controller.get_ports` but includes listener addresses
1393    and non-local endpoints.
1394
1395    .. versionadded:: 1.2.0
1396
1397    .. versionchanged:: 1.5.0
1398       Recognize listeners with IPv6 addresses.
1399
1400    :param stem.control.Listener listener_type: connection type being handled
1401      by the listeners we return
1402    :param object default: response if the query fails
1403
1404    :returns: **list** of **(address, port)** tuples for the available
1405      listeners
1406
1407    :raises: :class:`stem.ControllerError` if unable to determine the listeners
1408      and no default was provided
1409    """
1410
1411    listeners = self._get_cache(listener_type, 'listeners')
1412
1413    if listeners is None:
1414      proxy_addrs = []
1415      query = 'net/listeners/%s' % listener_type.lower()
1416
1417      try:
1418        for listener in self.get_info(query).split():
1419          if not (listener.startswith('"') and listener.endswith('"')):
1420            raise stem.ProtocolError("'GETINFO %s' responses are expected to be quoted: %s" % (query, listener))
1421          elif ':' not in listener:
1422            raise stem.ProtocolError("'GETINFO %s' had a listener without a colon: %s" % (query, listener))
1423
1424          listener = listener[1:-1]  # strip quotes
1425          addr, port = listener.rsplit(':', 1)
1426
1427          # Skip unix sockets, for instance...
1428          #
1429          # GETINFO net/listeners/control
1430          # 250-net/listeners/control="unix:/tmp/tor/socket"
1431          # 250 OK
1432
1433          if addr == 'unix':
1434            continue
1435
1436          if addr.startswith('[') and addr.endswith(']'):
1437            addr = addr[1:-1]  # unbracket ipv6 address
1438
1439          proxy_addrs.append((addr, port))
1440      except stem.InvalidArguments:
1441        # Tor version is old (pre-tor-0.2.2.26-beta), use get_conf() instead.
1442        # Some options (like the ORPort) can have optional attributes after the
1443        # actual port number.
1444
1445        port_option = {
1446          Listener.OR: 'ORPort',
1447          Listener.DIR: 'DirPort',
1448          Listener.SOCKS: 'SocksPort',
1449          Listener.TRANS: 'TransPort',
1450          Listener.NATD: 'NatdPort',
1451          Listener.DNS: 'DNSPort',
1452          Listener.CONTROL: 'ControlPort',
1453        }[listener_type]
1454
1455        listener_option = {
1456          Listener.OR: 'ORListenAddress',
1457          Listener.DIR: 'DirListenAddress',
1458          Listener.SOCKS: 'SocksListenAddress',
1459          Listener.TRANS: 'TransListenAddress',
1460          Listener.NATD: 'NatdListenAddress',
1461          Listener.DNS: 'DNSListenAddress',
1462          Listener.CONTROL: 'ControlListenAddress',
1463        }[listener_type]
1464
1465        port_value = self.get_conf(port_option).split()[0]
1466
1467        for listener in self.get_conf(listener_option, multiple = True):
1468          if ':' in listener:
1469            addr, port = listener.rsplit(':', 1)
1470
1471            if addr.startswith('[') and addr.endswith(']'):
1472              addr = addr[1:-1]  # unbracket ipv6 address
1473
1474            proxy_addrs.append((addr, port))
1475          else:
1476            proxy_addrs.append((listener, port_value))
1477
1478      # validate that address/ports are valid, and convert ports to ints
1479
1480      for addr, port in proxy_addrs:
1481        if not stem.util.connection.is_valid_ipv4_address(addr) and not stem.util.connection.is_valid_ipv6_address(addr):
1482          raise stem.ProtocolError('Invalid address for a %s listener: %s' % (listener_type, addr))
1483        elif not stem.util.connection.is_valid_port(port):
1484          raise stem.ProtocolError('Invalid port for a %s listener: %s' % (listener_type, port))
1485
1486      listeners = [(addr, int(port)) for (addr, port) in proxy_addrs]
1487      self._set_cache({listener_type: listeners}, 'listeners')
1488
1489    return listeners
1490
1491  @with_default()
1492  def get_accounting_stats(self, default = UNDEFINED):
1493    """
1494    get_accounting_stats(default = UNDEFINED)
1495
1496    Provides stats related to our relaying limitations if AccountingMax was set
1497    in our torrc.
1498
1499    .. versionadded:: 1.3.0
1500
1501    :param object default: response if the query fails
1502
1503    :returns: :class:`~stem.control.AccountingStats` with our accounting stats
1504
1505    :raises: :class:`stem.ControllerError` if unable to determine the listeners
1506      and no default was provided
1507    """
1508
1509    if self.get_info('accounting/enabled') != '1':
1510      raise stem.ControllerError("Accounting isn't enabled")
1511
1512    retrieved = time.time()
1513    status = self.get_info('accounting/hibernating')
1514    interval_end = self.get_info('accounting/interval-end')
1515    used = self.get_info('accounting/bytes')
1516    left = self.get_info('accounting/bytes-left')
1517
1518    interval_end = stem.util.str_tools._parse_timestamp(interval_end)
1519    used_read, used_written = [int(val) for val in used.split(' ', 1)]
1520    left_read, left_written = [int(val) for val in left.split(' ', 1)]
1521
1522    return AccountingStats(
1523      retrieved = retrieved,
1524      status = status,
1525      interval_end = interval_end,
1526      time_until_reset = max(0, calendar.timegm(interval_end.timetuple()) - int(retrieved)),
1527      read_bytes = used_read,
1528      read_bytes_left = left_read,
1529      read_limit = used_read + left_read,
1530      written_bytes = used_written,
1531      write_bytes_left = left_written,
1532      write_limit = used_written + left_written,
1533    )
1534
1535  def get_socks_listeners(self, default = UNDEFINED):
1536    """
1537    Provides the SOCKS **(address, port)** tuples that tor has open.
1538
1539    .. deprecated:: 1.2.0
1540       Use :func:`~stem.control.Controller.get_listeners` with
1541       **Listener.SOCKS** instead.
1542
1543    :param object default: response if the query fails
1544
1545    :returns: list of **(address, port)** tuples for the available SOCKS
1546      listeners
1547
1548    :raises: :class:`stem.ControllerError` if unable to determine the listeners
1549      and no default was provided
1550    """
1551
1552    return self.get_listeners(Listener.SOCKS, default)
1553
1554  @with_default()
1555  def get_protocolinfo(self, default = UNDEFINED):
1556    """
1557    get_protocolinfo(default = UNDEFINED)
1558
1559    A convenience method to get the protocol info of the controller.
1560
1561    :param object default: response if the query fails
1562
1563    :returns: :class:`~stem.response.protocolinfo.ProtocolInfoResponse` provided by tor
1564
1565    :raises:
1566      * :class:`stem.ProtocolError` if the PROTOCOLINFO response is
1567        malformed
1568      * :class:`stem.SocketError` if problems arise in establishing or
1569        using the socket
1570
1571      An exception is only raised if we weren't provided a default response.
1572    """
1573
1574    import stem.connection
1575    return stem.connection.get_protocolinfo(self)
1576
1577  @with_default()
1578  def get_user(self, default = UNDEFINED):
1579    """
1580    get_user(default = UNDEFINED)
1581
1582    Provides the user tor is running as. This often only works if tor is
1583    running locally. Also, most of its checks are platform dependent, and hence
1584    are not entirely reliable.
1585
1586    .. versionadded:: 1.1.0
1587
1588    :param object default: response if the query fails
1589
1590    :returns: str with the username tor is running as
1591    """
1592
1593    user = self._get_cache('user')
1594
1595    if user:
1596      return user
1597
1598    user = self.get_info('process/user', None)
1599
1600    if not user and self.is_localhost():
1601      pid = self.get_pid(None)
1602
1603      if pid:
1604        user = stem.util.system.user(pid)
1605
1606    if user:
1607      self._set_cache({'user': user})
1608      return user
1609    else:
1610      raise ValueError("Unable to resolve tor's user" if self.is_localhost() else "Tor isn't running locally")
1611
1612  @with_default()
1613  def get_pid(self, default = UNDEFINED):
1614    """
1615    get_pid(default = UNDEFINED)
1616
1617    Provides the process id of tor. This often only works if tor is running
1618    locally. Also, most of its checks are platform dependent, and hence are not
1619    entirely reliable.
1620
1621    .. versionadded:: 1.1.0
1622
1623    :param object default: response if the query fails
1624
1625    :returns: **int** for tor's pid
1626
1627    :raises: **ValueError** if unable to determine the pid and no default was
1628      provided
1629    """
1630
1631    pid = self._get_cache('pid')
1632
1633    if pid:
1634      return pid
1635
1636    getinfo_pid = self.get_info('process/pid', None)
1637
1638    if getinfo_pid and getinfo_pid.isdigit():
1639      pid = int(getinfo_pid)
1640
1641    if not pid and self.is_localhost():
1642      pid_file_path = self.get_conf('PidFile', None)
1643
1644      if pid_file_path is not None:
1645        with open(pid_file_path) as pid_file:
1646          pid_file_contents = pid_file.read().strip()
1647
1648          if pid_file_contents.isdigit():
1649            pid = int(pid_file_contents)
1650
1651      if not pid:
1652        pid = stem.util.system.pid_by_name('tor')
1653
1654      if not pid:
1655        control_socket = self.get_socket()
1656
1657        if isinstance(control_socket, stem.socket.ControlPort):
1658          pid = stem.util.system.pid_by_port(control_socket.port)
1659        elif isinstance(control_socket, stem.socket.ControlSocketFile):
1660          pid = stem.util.system.pid_by_open_file(control_socket.path)
1661
1662    if pid:
1663      self._set_cache({'pid': pid})
1664      return pid
1665    else:
1666      raise ValueError("Unable to resolve tor's pid" if self.is_localhost() else "Tor isn't running locally")
1667
1668  @with_default()
1669  def get_start_time(self, default = UNDEFINED):
1670    """
1671    get_start_time(default = UNDEFINED)
1672
1673    Provides when the tor process began.
1674
1675    .. versionadded:: 1.8.0
1676
1677    :param object default: response if the query fails
1678
1679    :returns: **float** for the unix timestamp of when the tor process began
1680
1681    :raises: **ValueError** if unable to determine when the process began and
1682      no default was provided
1683    """
1684
1685    start_time = self._get_cache('start_time')
1686
1687    if start_time:
1688      return start_time
1689
1690    if self.get_version() >= stem.version.Requirement.GETINFO_UPTIME:
1691      uptime = self.get_info('uptime', None)
1692
1693      if uptime:
1694        if not uptime.isdigit():
1695          raise ValueError("'GETINFO uptime' did not provide a valid numeric response: %s" % uptime)
1696
1697        start_time = time.time() - float(uptime)
1698
1699    if not start_time and self.is_localhost():
1700      # Tor doesn't yet support this GETINFO option, attempt to determine the
1701      # uptime of the process ourselves.
1702
1703      if not self.is_localhost():
1704        raise ValueError('Unable to determine the uptime when tor is not running locally')
1705
1706      pid = self.get_pid(None)
1707
1708      if not pid:
1709        raise ValueError('Unable to determine the pid of the tor process')
1710
1711      start_time = stem.util.system.start_time(pid)
1712
1713    if start_time:
1714      self._set_cache({'start_time': start_time})
1715      return start_time
1716    else:
1717      raise ValueError("Unable to resolve when tor began" if self.is_localhost() else "Tor isn't running locally")
1718
1719  @with_default()
1720  def get_uptime(self, default = UNDEFINED):
1721    """
1722    get_uptime(default = UNDEFINED)
1723
1724    Provides the duration in seconds that tor has been running.
1725
1726    .. versionadded:: 1.8.0
1727
1728    :param object default: response if the query fails
1729
1730    :returns: **float** for the number of seconds tor has been running
1731
1732    :raises: **ValueError** if unable to determine the uptime and no default
1733      was provided
1734    """
1735
1736    return time.time() - self.get_start_time()
1737
1738  def is_user_traffic_allowed(self):
1739    """
1740    Checks if we're likely to service direct user traffic. This essentially
1741    boils down to...
1742
1743      * If we're a bridge or guard relay, inbound connections are possibly from
1744        users.
1745
1746      * If our exit policy allows traffic then output connections are possibly
1747        from users.
1748
1749    Note the word 'likely'. These is a decent guess in practice, but not always
1750    correct. For instance, information about which flags we have are only
1751    fetched periodically.
1752
1753    This method is intended to help you avoid eavesdropping on user traffic.
1754    Monitoring user connections is not only unethical, but likely a violation
1755    of wiretapping laws.
1756
1757    .. versionadded:: 1.5.0
1758
1759    :returns: :class:`~stem.cotroller.UserTrafficAllowed` with **inbound** and
1760      **outbound** boolean attributes to indicate if we're likely servicing
1761      direct user traffic
1762    """
1763
1764    inbound_allowed, outbound_allowed = False, False
1765
1766    if self.get_conf('BridgeRelay', None) == '1':
1767      inbound_allowed = True
1768
1769    if self.get_conf('ORPort', None):
1770      if not inbound_allowed:
1771        consensus_entry = self.get_network_status(default = None)
1772        inbound_allowed = consensus_entry and 'Guard' in consensus_entry.flags
1773
1774      exit_policy = self.get_exit_policy(None)
1775      outbound_allowed = exit_policy and exit_policy.is_exiting_allowed()
1776
1777    return UserTrafficAllowed(inbound_allowed, outbound_allowed)
1778
1779  @with_default()
1780  def get_microdescriptor(self, relay = None, default = UNDEFINED):
1781    """
1782    get_microdescriptor(relay = None, default = UNDEFINED)
1783
1784    Provides the microdescriptor for the relay with the given fingerprint or
1785    nickname. If the relay identifier could be either a fingerprint *or*
1786    nickname then it's queried as a fingerprint.
1787
1788    If no **relay** is provided then this defaults to ourselves. Remember that
1789    this requires that we've retrieved our own descriptor from remote
1790    authorities so this both won't be available for newly started relays and
1791    may be up to around an hour out of date.
1792
1793    .. versionchanged:: 1.3.0
1794       Changed so we'd fetch our own descriptor if no 'relay' is provided.
1795
1796    :param str relay: fingerprint or nickname of the relay to be queried
1797    :param object default: response if the query fails
1798
1799    :returns: :class:`~stem.descriptor.microdescriptor.Microdescriptor` for the given relay
1800
1801    :raises:
1802      * :class:`stem.DescriptorUnavailable` if unable to provide a descriptor
1803        for the given relay
1804      * :class:`stem.ControllerError` if unable to query the descriptor
1805      * **ValueError** if **relay** doesn't conform with the pattern for being
1806        a fingerprint or nickname
1807
1808      An exception is only raised if we weren't provided a default response.
1809    """
1810
1811    if relay is None:
1812      try:
1813        relay = self.get_info('fingerprint')
1814      except stem.ControllerError as exc:
1815        raise stem.ControllerError('Unable to determine our own fingerprint: %s' % exc)
1816
1817    if stem.util.tor_tools.is_valid_fingerprint(relay):
1818      query = 'md/id/%s' % relay
1819    elif stem.util.tor_tools.is_valid_nickname(relay):
1820      query = 'md/name/%s' % relay
1821    else:
1822      raise ValueError("'%s' isn't a valid fingerprint or nickname" % relay)
1823
1824    try:
1825      desc_content = self.get_info(query, get_bytes = True)
1826    except stem.InvalidArguments as exc:
1827      if str(exc).startswith('GETINFO request contained unrecognized keywords:'):
1828        raise stem.DescriptorUnavailable("Tor was unable to provide the descriptor for '%s'" % relay)
1829      else:
1830        raise
1831
1832    if not desc_content:
1833      raise stem.DescriptorUnavailable('Descriptor information is unavailable, tor might still be downloading it')
1834
1835    return stem.descriptor.microdescriptor.Microdescriptor(desc_content)
1836
1837  @with_default(yields = True)
1838  def get_microdescriptors(self, default = UNDEFINED):
1839    """
1840    get_microdescriptors(default = UNDEFINED)
1841
1842    Provides an iterator for all of the microdescriptors that tor currently
1843    knows about.
1844
1845    Prior to Tor 0.3.5.1 this information was not available via the control
1846    protocol. When connected to prior versions we read the microdescriptors
1847    directly from disk instead, which will not work remotely or if our process
1848    lacks read permissions.
1849
1850    :param list default: items to provide if the query fails
1851
1852    :returns: iterates over
1853      :class:`~stem.descriptor.microdescriptor.Microdescriptor` for relays in
1854      the tor network
1855
1856    :raises: :class:`stem.ControllerError` if unable to query tor and no
1857      default was provided
1858    """
1859
1860    if self.get_version() >= stem.version.Requirement.GETINFO_MICRODESCRIPTORS:
1861      desc_content = self.get_info('md/all', get_bytes = True)
1862
1863      if not desc_content:
1864        raise stem.DescriptorUnavailable('Descriptor information is unavailable, tor might still be downloading it')
1865
1866      for desc in stem.descriptor.microdescriptor._parse_file(io.BytesIO(desc_content)):
1867        yield desc
1868    else:
1869      # TODO: remove when tor versions that require this are obsolete
1870
1871      data_directory = self.get_conf('DataDirectory', None)
1872
1873      if data_directory is None:
1874        raise stem.OperationFailed(message = "Unable to determine tor's data directory")
1875
1876      if not os.path.exists(data_directory):
1877        raise stem.OperationFailed(message = "Data directory reported by tor doesn't exist (%s)" % data_directory)
1878
1879      microdescriptor_file = None
1880
1881      for filename in ('cached-microdescs', 'cached-microdescs.new'):
1882        cached_descriptors = os.path.join(data_directory, filename)
1883
1884        if os.path.exists(cached_descriptors):
1885          microdescriptor_file = cached_descriptors
1886          break
1887
1888      if microdescriptor_file is None:
1889        raise stem.OperationFailed(message = "Data directory doesn't contain cached microdescriptors (%s)" % data_directory)
1890
1891      for desc in stem.descriptor.parse_file(microdescriptor_file):
1892        # It shouldn't be possible for these to be something other than
1893        # microdescriptors but as the saying goes: trust but verify.
1894
1895        if not isinstance(desc, stem.descriptor.microdescriptor.Microdescriptor):
1896          raise stem.OperationFailed(message = 'BUG: Descriptor reader provided non-microdescriptor content (%s)' % type(desc))
1897
1898        yield desc
1899
1900  @with_default()
1901  def get_server_descriptor(self, relay = None, default = UNDEFINED):
1902    """
1903    get_server_descriptor(relay = None, default = UNDEFINED)
1904
1905    Provides the server descriptor for the relay with the given fingerprint or
1906    nickname. If the relay identifier could be either a fingerprint *or*
1907    nickname then it's queried as a fingerprint.
1908
1909    If no **relay** is provided then this defaults to ourselves. Remember that
1910    this requires that we've retrieved our own descriptor from remote
1911    authorities so this both won't be available for newly started relays and
1912    may be up to around an hour out of date.
1913
1914    **As of Tor version 0.2.3.25 relays no longer get server descriptors by
1915    default.** It's advised that you use microdescriptors instead, but if you
1916    really need server descriptors then you can get them by setting
1917    'UseMicrodescriptors 0'.
1918
1919    .. versionchanged:: 1.3.0
1920       Changed so we'd fetch our own descriptor if no 'relay' is provided.
1921
1922    :param str relay: fingerprint or nickname of the relay to be queried
1923    :param object default: response if the query fails
1924
1925    :returns: :class:`~stem.descriptor.server_descriptor.RelayDescriptor` for the given relay
1926
1927    :raises:
1928      * :class:`stem.DescriptorUnavailable` if unable to provide a descriptor
1929        for the given relay
1930      * :class:`stem.ControllerError` if unable to query the descriptor
1931      * **ValueError** if **relay** doesn't conform with the pattern for being
1932        a fingerprint or nickname
1933
1934      An exception is only raised if we weren't provided a default response.
1935    """
1936
1937    try:
1938      if relay is None:
1939        try:
1940          relay = self.get_info('fingerprint')
1941        except stem.ControllerError as exc:
1942          raise stem.ControllerError('Unable to determine our own fingerprint: %s' % exc)
1943
1944      if stem.util.tor_tools.is_valid_fingerprint(relay):
1945        query = 'desc/id/%s' % relay
1946      elif stem.util.tor_tools.is_valid_nickname(relay):
1947        query = 'desc/name/%s' % relay
1948      else:
1949        raise ValueError("'%s' isn't a valid fingerprint or nickname" % relay)
1950
1951      try:
1952        desc_content = self.get_info(query, get_bytes = True)
1953      except stem.InvalidArguments as exc:
1954        if str(exc).startswith('GETINFO request contained unrecognized keywords:'):
1955          raise stem.DescriptorUnavailable("Tor was unable to provide the descriptor for '%s'" % relay)
1956        else:
1957          raise
1958
1959      if not desc_content:
1960        raise stem.DescriptorUnavailable('Descriptor information is unavailable, tor might still be downloading it')
1961
1962      return stem.descriptor.server_descriptor.RelayDescriptor(desc_content)
1963    except:
1964      if not self._is_server_descriptors_available():
1965        raise ValueError(SERVER_DESCRIPTORS_UNSUPPORTED)
1966
1967      raise
1968
1969  @with_default(yields = True)
1970  def get_server_descriptors(self, default = UNDEFINED):
1971    """
1972    get_server_descriptors(default = UNDEFINED)
1973
1974    Provides an iterator for all of the server descriptors that tor currently
1975    knows about.
1976
1977    **As of Tor version 0.2.3.25 relays no longer get server descriptors by
1978    default.** It's advised that you use microdescriptors instead, but if you
1979    really need server descriptors then you can get them by setting
1980    'UseMicrodescriptors 0'.
1981
1982    :param list default: items to provide if the query fails
1983
1984    :returns: iterates over
1985      :class:`~stem.descriptor.server_descriptor.RelayDescriptor` for relays in
1986      the tor network
1987
1988    :raises: :class:`stem.ControllerError` if unable to query tor and no
1989      default was provided
1990    """
1991
1992    # TODO: We should iterate over the descriptors as they're read from the
1993    # socket rather than reading the whole thing into memory.
1994    #
1995    # https://trac.torproject.org/8248
1996
1997    desc_content = self.get_info('desc/all-recent', get_bytes = True)
1998
1999    if not desc_content:
2000      if not self._is_server_descriptors_available():
2001        raise stem.ControllerError(SERVER_DESCRIPTORS_UNSUPPORTED)
2002      else:
2003        raise stem.DescriptorUnavailable('Descriptor information is unavailable, tor might still be downloading it')
2004
2005    for desc in stem.descriptor.server_descriptor._parse_file(io.BytesIO(desc_content)):
2006      yield desc
2007
2008  def _is_server_descriptors_available(self):
2009    """
2010    Checks to see if tor server descriptors should be available or not.
2011    """
2012
2013    # TODO: Replace with a 'GETINFO desc/download-enabled' request when they're
2014    # widely available...
2015    #
2016    #   https://gitweb.torproject.org/torspec.git/commit/?id=378699c
2017
2018    return self.get_version() < stem.version.Requirement.MICRODESCRIPTOR_IS_DEFAULT or \
2019           self.get_conf('UseMicrodescriptors', None) == '0'
2020
2021  @with_default()
2022  def get_network_status(self, relay = None, default = UNDEFINED):
2023    """
2024    get_network_status(relay = None, default = UNDEFINED)
2025
2026    Provides the router status entry for the relay with the given fingerprint
2027    or nickname. If the relay identifier could be either a fingerprint *or*
2028    nickname then it's queried as a fingerprint.
2029
2030    If no **relay** is provided then this defaults to ourselves. Remember that
2031    this requires that we've retrieved our own descriptor from remote
2032    authorities so this both won't be available for newly started relays and
2033    may be up to around an hour out of date.
2034
2035    .. versionchanged:: 1.3.0
2036       Changed so we'd fetch our own descriptor if no 'relay' is provided.
2037
2038    :param str relay: fingerprint or nickname of the relay to be queried
2039    :param object default: response if the query fails
2040
2041    :returns: :class:`~stem.descriptor.router_status_entry.RouterStatusEntryV3`
2042      for the given relay
2043
2044    :raises:
2045      * :class:`stem.DescriptorUnavailable` if unable to provide a descriptor
2046        for the given relay
2047      * :class:`stem.ControllerError` if unable to query the descriptor
2048      * **ValueError** if **relay** doesn't conform with the pattern for being
2049        a fingerprint or nickname
2050
2051      An exception is only raised if we weren't provided a default response.
2052    """
2053
2054    if relay is None:
2055      try:
2056        relay = self.get_info('fingerprint')
2057      except stem.ControllerError as exc:
2058        raise stem.ControllerError('Unable to determine our own fingerprint: %s' % exc)
2059
2060    if stem.util.tor_tools.is_valid_fingerprint(relay):
2061      query = 'ns/id/%s' % relay
2062    elif stem.util.tor_tools.is_valid_nickname(relay):
2063      query = 'ns/name/%s' % relay
2064    else:
2065      raise ValueError("'%s' isn't a valid fingerprint or nickname" % relay)
2066
2067    try:
2068      desc_content = self.get_info(query, get_bytes = True)
2069    except stem.InvalidArguments as exc:
2070      if str(exc).startswith('GETINFO request contained unrecognized keywords:'):
2071        raise stem.DescriptorUnavailable("Tor was unable to provide the descriptor for '%s'" % relay)
2072      else:
2073        raise
2074
2075    if not desc_content:
2076      raise stem.DescriptorUnavailable('Descriptor information is unavailable, tor might still be downloading it')
2077
2078    return stem.descriptor.router_status_entry.RouterStatusEntryV3(desc_content)
2079
2080  @with_default(yields = True)
2081  def get_network_statuses(self, default = UNDEFINED):
2082    """
2083    get_network_statuses(default = UNDEFINED)
2084
2085    Provides an iterator for all of the router status entries that tor
2086    currently knows about.
2087
2088    :param list default: items to provide if the query fails
2089
2090    :returns: iterates over
2091      :class:`~stem.descriptor.router_status_entry.RouterStatusEntryV3` for
2092      relays in the tor network
2093
2094    :raises: :class:`stem.ControllerError` if unable to query tor and no
2095      default was provided
2096    """
2097
2098    # TODO: We should iterate over the descriptors as they're read from the
2099    # socket rather than reading the whole thing into memory.
2100    #
2101    # https://trac.torproject.org/8248
2102
2103    desc_content = self.get_info('ns/all', get_bytes = True)
2104
2105    if not desc_content:
2106      raise stem.DescriptorUnavailable('Descriptor information is unavailable, tor might still be downloading it')
2107
2108    desc_iterator = stem.descriptor.router_status_entry._parse_file(
2109      io.BytesIO(desc_content),
2110      False,
2111      entry_class = stem.descriptor.router_status_entry.RouterStatusEntryV3,
2112    )
2113
2114    for desc in desc_iterator:
2115      yield desc
2116
2117  @with_default()
2118  def get_hidden_service_descriptor(self, address, default = UNDEFINED, servers = None, await_result = True, timeout = None):
2119    """
2120    get_hidden_service_descriptor(address, default = UNDEFINED, servers = None, await_result = True)
2121
2122    Provides the descriptor for a hidden service. The **address** is the
2123    '.onion' address of the hidden service (for instance 3g2upl4pq6kufc4m.onion
2124    for DuckDuckGo).
2125
2126    If **await_result** is **True** then this blocks until we either receive
2127    the descriptor or the request fails. If **False** this returns right away.
2128
2129    **This method only supports v2 hidden services, not v3.** (:trac:`25417`)
2130
2131    .. versionadded:: 1.4.0
2132
2133    .. versionchanged:: 1.7.0
2134       Added the timeout argument.
2135
2136    :param str address: address of the hidden service descriptor, the '.onion' suffix is optional
2137    :param object default: response if the query fails
2138    :param list servers: requrest the descriptor from these specific servers
2139    :param float timeout: seconds to wait when **await_result** is **True**
2140
2141    :returns: :class:`~stem.descriptor.hidden_service.HiddenServiceDescriptorV2`
2142      for the given service if **await_result** is **True**, or **None** otherwise
2143
2144    :raises:
2145      * :class:`stem.DescriptorUnavailable` if **await_result** is **True** and
2146        unable to provide a descriptor for the given service
2147      * :class:`stem.Timeout` if **timeout** was reached
2148      * :class:`stem.ControllerError` if unable to query the descriptor
2149      * **ValueError** if **address** doesn't conform with the pattern of a
2150        hidden service address
2151
2152      An exception is only raised if we weren't provided a default response.
2153    """
2154
2155    if address.endswith('.onion'):
2156      address = address[:-6]
2157
2158    if not stem.util.tor_tools.is_valid_hidden_service_address(address):
2159      raise ValueError("'%s.onion' isn't a valid hidden service address" % address)
2160
2161    if self.get_version() < stem.version.Requirement.HSFETCH:
2162      raise stem.UnsatisfiableRequest(message = 'HSFETCH was added in tor version %s' % stem.version.Requirement.HSFETCH)
2163
2164    hs_desc_queue, hs_desc_listener = queue.Queue(), None
2165    hs_desc_content_queue, hs_desc_content_listener = queue.Queue(), None
2166    start_time = time.time()
2167
2168    if await_result:
2169      def hs_desc_listener(event):
2170        hs_desc_queue.put(event)
2171
2172      def hs_desc_content_listener(event):
2173        hs_desc_content_queue.put(event)
2174
2175      self.add_event_listener(hs_desc_listener, EventType.HS_DESC)
2176      self.add_event_listener(hs_desc_content_listener, EventType.HS_DESC_CONTENT)
2177
2178    try:
2179      request = 'HSFETCH %s' % address
2180
2181      if servers:
2182        request += ' ' + ' '.join(['SERVER=%s' % s for s in servers])
2183
2184      response = self.msg(request)
2185      stem.response.convert('SINGLELINE', response)
2186
2187      if not response.is_ok():
2188        raise stem.ProtocolError('HSFETCH returned unexpected response code: %s' % response.code)
2189
2190      if not await_result:
2191        return None  # not waiting, so nothing to provide back
2192      else:
2193        while True:
2194          event = _get_with_timeout(hs_desc_content_queue, timeout, start_time)
2195
2196          if event.address == address:
2197            if event.descriptor:
2198              return event.descriptor
2199            else:
2200              # no descriptor, looking through HS_DESC to figure out why
2201
2202              while True:
2203                event = _get_with_timeout(hs_desc_queue, timeout, start_time)
2204
2205                if event.address == address and event.action == stem.HSDescAction.FAILED:
2206                  if event.reason == stem.HSDescReason.NOT_FOUND:
2207                    raise stem.DescriptorUnavailable('No running hidden service at %s.onion' % address)
2208                  else:
2209                    raise stem.DescriptorUnavailable('Unable to retrieve the descriptor for %s.onion (retrieved from %s): %s' % (address, event.directory_fingerprint, event.reason))
2210    finally:
2211      if hs_desc_listener:
2212        self.remove_event_listener(hs_desc_listener)
2213
2214      if hs_desc_content_listener:
2215        self.remove_event_listener(hs_desc_content_listener)
2216
2217  def get_conf(self, param, default = UNDEFINED, multiple = False):
2218    """
2219    get_conf(param, default = UNDEFINED, multiple = False)
2220
2221    Queries the current value for a configuration option. Some configuration
2222    options (like the ExitPolicy) can have multiple values. This provides a
2223    **list** with all of the values if **multiple** is **True**. Otherwise this
2224    will be a **str** with the first value.
2225
2226    If provided with a **default** then that is provided if the configuration
2227    option was unset or the query fails (invalid configuration option, error
2228    response, control port closed, initiated, etc).
2229
2230    If the configuration value is unset and no **default** was given then this
2231    provides **None** if **multiple** was **False** and an empty list if it was
2232    **True**.
2233
2234    :param str param: configuration option to be queried
2235    :param object default: response if the option is unset or the query fails
2236    :param bool multiple: if **True** then provides a list with all of the
2237      present values (this is an empty list if the config option is unset)
2238
2239    :returns:
2240      Response depends upon how we were called as follows...
2241
2242      * **str** with the configuration value if **multiple** was **False**,
2243        **None** if it was unset
2244      * **list** with the response strings if multiple was **True**
2245      * default if one was provided and the configuration option was either
2246        unset or our call failed
2247
2248    :raises:
2249      * :class:`stem.ControllerError` if the call fails and we weren't
2250        provided a default response
2251      * :class:`stem.InvalidArguments` if the configuration option
2252        requested was invalid
2253    """
2254
2255    # Config options are case insensitive and don't contain whitespace. Using
2256    # strip so the following check will catch whitespace-only params.
2257
2258    param = param.lower().strip()
2259
2260    if not param:
2261      return default if default != UNDEFINED else None
2262
2263    entries = self.get_conf_map(param, default, multiple)
2264    return _case_insensitive_lookup(entries, param, default)
2265
2266  def get_conf_map(self, params, default = UNDEFINED, multiple = True):
2267    """
2268    get_conf_map(params, default = UNDEFINED, multiple = True)
2269
2270    Similar to :func:`~stem.control.Controller.get_conf` but queries multiple
2271    configuration options, providing back a mapping of those options to their
2272    values.
2273
2274    There are three use cases for GETCONF:
2275
2276      1. a single value is provided (e.g. **ControlPort**)
2277      2. multiple values are provided for the option (e.g. **ExitPolicy**)
2278      3. a set of options that weren't necessarily requested are returned (for
2279         instance querying **HiddenServiceOptions** gives **HiddenServiceDir**,
2280         **HiddenServicePort**, etc)
2281
2282    The vast majority of the options fall into the first two categories, in
2283    which case calling :func:`~stem.control.Controller.get_conf` is sufficient.
2284    However, for batch queries or the special options that give a set of values
2285    this provides back the full response. As of tor version 0.2.1.25
2286    **HiddenServiceOptions** was the only option that falls into the third
2287    category.
2288
2289    **Note:** HiddenServiceOptions are best retrieved via the
2290    :func:`~stem.control.Controller.get_hidden_service_conf` method instead.
2291
2292    :param str,list params: configuration option(s) to be queried
2293    :param object default: value for the mappings if the configuration option
2294      is either undefined or the query fails
2295    :param bool multiple: if **True** then the values provided are lists with
2296      all of the present values
2297
2298    :returns:
2299      **dict** of the 'config key => value' mappings. The value is a...
2300
2301      * **str** if **multiple** is **False**, **None** if the configuration
2302        option is unset
2303      * **list** if **multiple** is **True**
2304      * the **default** if it was set and the value was either undefined or our
2305        lookup failed
2306
2307    :raises:
2308      * :class:`stem.ControllerError` if the call fails and we weren't provided
2309        a default response
2310      * :class:`stem.InvalidArguments` if the configuration option requested
2311        was invalid
2312    """
2313
2314    start_time = time.time()
2315    reply = {}
2316
2317    if stem.util._is_str(params):
2318      params = [params]
2319
2320    # remove strings which contain only whitespace
2321    params = [entry for entry in params if entry.strip()]
2322
2323    if params == []:
2324      return {}
2325
2326    # translate context sensitive options
2327    lookup_params = set([MAPPED_CONFIG_KEYS.get(entry, entry) for entry in params])
2328
2329    # check for cached results
2330
2331    from_cache = [param.lower() for param in lookup_params]
2332    cached_results = self._get_cache_map(from_cache, 'getconf')
2333
2334    for key in cached_results:
2335      user_expected_key = _case_insensitive_lookup(lookup_params, key)
2336      reply[user_expected_key] = cached_results[key]
2337      lookup_params.remove(user_expected_key)
2338
2339    # if everything was cached then short circuit making the query
2340    if not lookup_params:
2341      if LOG_CACHE_FETCHES:
2342        log.trace('GETCONF %s (cache fetch)' % ' '.join(reply.keys()))
2343
2344      return self._get_conf_dict_to_response(reply, default, multiple)
2345
2346    try:
2347      response = self.msg('GETCONF %s' % ' '.join(lookup_params))
2348      stem.response.convert('GETCONF', response)
2349      reply.update(response.entries)
2350
2351      if self.is_caching_enabled():
2352        to_cache = dict((k.lower(), v) for k, v in response.entries.items())
2353
2354        self._set_cache(to_cache, 'getconf')
2355
2356      # Maps the entries back to the parameters that the user requested so the
2357      # capitalization matches (ie, if they request "exitpolicy" then that
2358      # should be the key rather than "ExitPolicy"). When the same
2359      # configuration key is provided multiple times this determines the case
2360      # based on the first and ignores the rest.
2361      #
2362      # This retains the tor provided camel casing of MAPPED_CONFIG_KEYS
2363      # entries since the user didn't request those by their key, so we can't
2364      # be sure what they wanted.
2365
2366      for key in list(reply):
2367        if not key.lower() in MAPPED_CONFIG_KEYS.values():
2368          user_expected_key = _case_insensitive_lookup(params, key, key)
2369
2370          if key != user_expected_key:
2371            reply[user_expected_key] = reply[key]
2372            del reply[key]
2373
2374      log.debug('GETCONF %s (runtime: %0.4f)' % (' '.join(lookup_params), time.time() - start_time))
2375      return self._get_conf_dict_to_response(reply, default, multiple)
2376    except stem.ControllerError as exc:
2377      log.debug('GETCONF %s (failed: %s)' % (' '.join(lookup_params), exc))
2378
2379      if default != UNDEFINED:
2380        return dict((param, default) for param in params)
2381      else:
2382        raise
2383
2384  def _get_conf_dict_to_response(self, config_dict, default, multiple):
2385    """
2386    Translates a dictionary of 'config key => [value1, value2...]' into the
2387    return value of :func:`~stem.control.Controller.get_conf_map`, taking into
2388    account what the caller requested.
2389    """
2390
2391    return_dict = {}
2392
2393    for key, values in list(config_dict.items()):
2394      if values == []:
2395        # config option was unset
2396        if default != UNDEFINED:
2397          return_dict[key] = default
2398        else:
2399          return_dict[key] = [] if multiple else None
2400      else:
2401        return_dict[key] = values if multiple else values[0]
2402
2403    return return_dict
2404
2405  @with_default()
2406  def is_set(self, param, default = UNDEFINED):
2407    """
2408    is_set(param, default = UNDEFINED)
2409
2410    Checks if a configuration option differs from its default or not.
2411
2412    .. versionadded:: 1.5.0
2413
2414    :param str param: configuration option to check
2415    :param object default: response if the query fails
2416
2417    :returns: **True** if option differs from its default and **False**
2418      otherwise
2419
2420    :raises: :class:`stem.ControllerError` if the call fails and we weren't
2421      provided a default response
2422    """
2423
2424    return param in self._get_custom_options()
2425
2426  def _get_custom_options(self):
2427    result = self._get_cache('get_custom_options')
2428
2429    if not result:
2430      config_lines = self.get_info('config-text').splitlines()
2431
2432      # Tor provides some config options even if they haven't been set...
2433      #
2434      # https://trac.torproject.org/projects/tor/ticket/2362
2435      # https://trac.torproject.org/projects/tor/ticket/17909
2436
2437      default_lines = (
2438        'Log notice stdout',
2439        'Log notice file /var/log/tor/log',
2440        'DataDirectory /home/%s/.tor' % self.get_user('undefined'),
2441        'HiddenServiceStatistics 0',
2442      )
2443
2444      for line in default_lines:
2445        if line in config_lines:
2446          config_lines.remove(line)
2447
2448      result = dict([line.split(' ', 1) for line in config_lines])
2449      self._set_cache({'get_custom_options': result})
2450
2451    return result
2452
2453  def set_conf(self, param, value):
2454    """
2455    Changes the value of a tor configuration option. Our value can be any of
2456    the following...
2457
2458    * a string to set a single value
2459    * a list of strings to set a series of values (for instance the ExitPolicy)
2460    * None to either set the value to 0/NULL
2461
2462    :param str param: configuration option to be set
2463    :param str,list value: value to set the parameter to
2464
2465    :raises:
2466      * :class:`stem.ControllerError` if the call fails
2467      * :class:`stem.InvalidArguments` if configuration options
2468        requested was invalid
2469      * :class:`stem.InvalidRequest` if the configuration setting is
2470        impossible or if there's a syntax error in the configuration values
2471    """
2472
2473    self.set_options({param: value}, False)
2474
2475  def reset_conf(self, *params):
2476    """
2477    Reverts one or more parameters to their default values.
2478
2479    :param str params: configuration option to be reset
2480
2481    :raises:
2482      * :class:`stem.ControllerError` if the call fails
2483      * :class:`stem.InvalidArguments` if configuration options requested was invalid
2484      * :class:`stem.InvalidRequest` if the configuration setting is
2485        impossible or if there's a syntax error in the configuration values
2486    """
2487
2488    self.set_options(dict([(entry, None) for entry in params]), True)
2489
2490  def set_options(self, params, reset = False):
2491    """
2492    Changes multiple tor configuration options via either a SETCONF or
2493    RESETCONF query. Both behave identically unless our value is None, in which
2494    case SETCONF sets the value to 0 or NULL, and RESETCONF returns it to its
2495    default value. This accepts str, list, or None values in a similar fashion
2496    to :func:`~stem.control.Controller.set_conf`. For example...
2497
2498    ::
2499
2500      my_controller.set_options({
2501        'Nickname': 'caerSidi',
2502        'ExitPolicy': ['accept *:80', 'accept *:443', 'reject *:*'],
2503        'ContactInfo': 'caerSidi-exit@someplace.com',
2504        'Log': None,
2505      })
2506
2507    The params can optionally be a list of key/value tuples, though the only
2508    reason this type of argument would be useful is for hidden service
2509    configuration (those options are order dependent).
2510
2511    :param dict,list params: mapping of configuration options to the values
2512      we're setting it to
2513    :param bool reset: issues a RESETCONF, returning **None** values to their
2514      defaults if **True**
2515
2516    :raises:
2517      * :class:`stem.ControllerError` if the call fails
2518      * :class:`stem.InvalidArguments` if configuration options
2519        requested was invalid
2520      * :class:`stem.InvalidRequest` if the configuration setting is
2521        impossible or if there's a syntax error in the configuration values
2522    """
2523
2524    start_time = time.time()
2525
2526    # constructs the SETCONF or RESETCONF query
2527    query_comp = ['RESETCONF' if reset else 'SETCONF']
2528
2529    if isinstance(params, dict):
2530      params = list(params.items())
2531
2532    for param, value in params:
2533      if isinstance(value, str):
2534        query_comp.append('%s="%s"' % (param, value.strip()))
2535      elif isinstance(value, collections.Iterable):
2536        query_comp.extend(['%s="%s"' % (param, val.strip()) for val in value])
2537      elif not value:
2538        query_comp.append(param)
2539      else:
2540        raise ValueError('Cannot set %s to %s since the value was a %s but we only accept strings' % (param, value, type(value).__name__))
2541
2542    query = ' '.join(query_comp)
2543    response = self.msg(query)
2544    stem.response.convert('SINGLELINE', response)
2545
2546    if response.is_ok():
2547      log.debug('%s (runtime: %0.4f)' % (query, time.time() - start_time))
2548
2549      if self.is_caching_enabled():
2550        # clear cache for params; the CONF_CHANGED event will set cache for changes
2551        to_cache = dict((k.lower(), None) for k, v in params)
2552        self._set_cache(to_cache, 'getconf')
2553        self._confchanged_cache_invalidation(dict(params))
2554    else:
2555      log.debug('%s (failed, code: %s, message: %s)' % (query, response.code, response.message))
2556      immutable_params = [k for k, v in params if stem.util.str_tools._to_unicode(k).lower() in IMMUTABLE_CONFIG_OPTIONS]
2557
2558      if immutable_params:
2559        raise stem.InvalidArguments(message = "%s cannot be changed while tor's running" % ', '.join(sorted(immutable_params)), arguments = immutable_params)
2560
2561      if response.code == '552':
2562        if response.message.startswith("Unrecognized option: Unknown option '"):
2563          key = response.message[37:response.message.find("'", 37)]
2564          raise stem.InvalidArguments(response.code, response.message, [key])
2565        raise stem.InvalidRequest(response.code, response.message)
2566      elif response.code in ('513', '553'):
2567        raise stem.InvalidRequest(response.code, response.message)
2568      else:
2569        raise stem.ProtocolError('Returned unexpected status code: %s' % response.code)
2570
2571  @with_default()
2572  def get_hidden_service_conf(self, default = UNDEFINED):
2573    """
2574    get_hidden_service_conf(default = UNDEFINED)
2575
2576    This provides a mapping of hidden service directories to their
2577    attribute's key/value pairs. All hidden services are assured to have a
2578    'HiddenServicePort', but other entries may or may not exist.
2579
2580    ::
2581
2582      {
2583        "/var/lib/tor/hidden_service_empty/": {
2584          "HiddenServicePort": [
2585          ]
2586        },
2587        "/var/lib/tor/hidden_service_with_two_ports/": {
2588          "HiddenServiceAuthorizeClient": "stealth a, b",
2589          "HiddenServicePort": [
2590            (8020, "127.0.0.1", 8020),  # the ports order is kept
2591            (8021, "127.0.0.1", 8021)
2592          ],
2593          "HiddenServiceVersion": "2"
2594        },
2595      }
2596
2597    .. versionadded:: 1.3.0
2598
2599    :param object default: response if the query fails
2600
2601    :returns: **dict** with the hidden service configuration
2602
2603    :raises: :class:`stem.ControllerError` if the call fails and we weren't
2604      provided a default response
2605    """
2606
2607    service_dir_map = self._get_cache('hidden_service_conf')
2608
2609    if service_dir_map is not None:
2610      if LOG_CACHE_FETCHES:
2611        log.trace('GETCONF HiddenServiceOptions (cache fetch)')
2612
2613      return service_dir_map
2614
2615    start_time = time.time()
2616
2617    try:
2618      response = self.msg('GETCONF HiddenServiceOptions')
2619      stem.response.convert('GETCONF', response)
2620      log.debug('GETCONF HiddenServiceOptions (runtime: %0.4f)' %
2621                (time.time() - start_time))
2622    except stem.ControllerError as exc:
2623      log.debug('GETCONF HiddenServiceOptions (failed: %s)' % exc)
2624      raise
2625
2626    service_dir_map = OrderedDict()
2627    directory = None
2628
2629    for status_code, divider, content in response.content():
2630      if content == 'HiddenServiceOptions':
2631        continue
2632
2633      if '=' not in content:
2634        continue
2635
2636      k, v = content.split('=', 1)
2637
2638      if k == 'HiddenServiceDir':
2639        directory = v
2640        service_dir_map[directory] = {'HiddenServicePort': []}
2641      elif k == 'HiddenServicePort':
2642        port = target_port = v
2643        target_address = '127.0.0.1'
2644
2645        if not v.isdigit():
2646          port, target = v.split()
2647
2648          if target.isdigit():
2649            target_port = target
2650          else:
2651            target_address, target_port = target.rsplit(':', 1)
2652
2653        if not stem.util.connection.is_valid_port(port):
2654          raise stem.ProtocolError('GETCONF provided an invalid HiddenServicePort port (%s): %s' % (port, content))
2655        elif not stem.util.connection.is_valid_ipv4_address(target_address):
2656          raise stem.ProtocolError('GETCONF provided an invalid HiddenServicePort target address (%s): %s' % (target_address, content))
2657        elif not stem.util.connection.is_valid_port(target_port):
2658          raise stem.ProtocolError('GETCONF provided an invalid HiddenServicePort target port (%s): %s' % (target_port, content))
2659
2660        service_dir_map[directory]['HiddenServicePort'].append((int(port), target_address, int(target_port)))
2661      else:
2662        service_dir_map[directory][k] = v
2663
2664    self._set_cache({'hidden_service_conf': service_dir_map})
2665    return service_dir_map
2666
2667  def set_hidden_service_conf(self, conf):
2668    """
2669    Update all the configured hidden services from a dictionary having
2670    the same format as
2671    :func:`~stem.control.Controller.get_hidden_service_conf`.
2672
2673    For convenience the HiddenServicePort entries can be an integer, string, or
2674    tuple. If an **int** then we treat it as just a port. If a **str** we pass
2675    that directly as the HiddenServicePort. And finally, if a **tuple** then
2676    it's expected to be the **(port, target_address, target_port)** as provided
2677    by :func:`~stem.control.Controller.get_hidden_service_conf`.
2678
2679    This is to say the following three are equivalent...
2680
2681    ::
2682
2683      "HiddenServicePort": [
2684        80,
2685        '80 127.0.0.1:80',
2686        (80, '127.0.0.1', 80),
2687      ]
2688
2689    .. versionadded:: 1.3.0
2690
2691    :param dict conf: configuration dictionary
2692
2693    :raises:
2694      * :class:`stem.ControllerError` if the call fails
2695      * :class:`stem.InvalidArguments` if configuration options
2696        requested was invalid
2697      * :class:`stem.InvalidRequest` if the configuration setting is
2698        impossible or if there's a syntax error in the configuration values
2699    """
2700
2701    # If we're not adding or updating any hidden services then call RESETCONF
2702    # so we drop existing values. Otherwise calling SETCONF is a no-op.
2703
2704    if not conf:
2705      self.reset_conf('HiddenServiceDir')
2706      return
2707
2708    # Convert conf dictionary into a list of ordered config tuples
2709
2710    hidden_service_options = []
2711
2712    for directory in conf:
2713      hidden_service_options.append(('HiddenServiceDir', directory))
2714
2715      for k, v in list(conf[directory].items()):
2716        if k == 'HiddenServicePort':
2717          for entry in v:
2718            if isinstance(entry, int):
2719              entry = '%s 127.0.0.1:%s' % (entry, entry)
2720            elif isinstance(entry, str):
2721              pass  # just pass along what the user gave us
2722            elif isinstance(entry, tuple):
2723              port, target_address, target_port = entry
2724              entry = '%s %s:%s' % (port, target_address, target_port)
2725
2726            hidden_service_options.append(('HiddenServicePort', entry))
2727        else:
2728          hidden_service_options.append((k, str(v)))
2729
2730    self.set_options(hidden_service_options)
2731
2732  def create_hidden_service(self, path, port, target_address = None, target_port = None, auth_type = None, client_names = None):
2733    """
2734    Create a new hidden service. If the directory is already present, a
2735    new port is added.
2736
2737    Our *.onion address is fetched by reading the hidden service directory.
2738    However, this directory is only readable by the tor user, so if unavailable
2739    the **hostname** will be **None**.
2740
2741    **As of Tor 0.2.7.1 there's two ways for creating hidden services, and this
2742    method is no longer recommended.** Rather, try using
2743    :func:`~stem.control.Controller.create_ephemeral_hidden_service` instead.
2744
2745    .. versionadded:: 1.3.0
2746
2747    .. versionchanged:: 1.4.0
2748       Added the auth_type and client_names arguments.
2749
2750    :param str path: path for the hidden service's data directory
2751    :param int port: hidden service port
2752    :param str target_address: address of the service, by default 127.0.0.1
2753    :param int target_port: port of the service, by default this is the same as
2754      **port**
2755    :param str auth_type: authentication type: basic, stealth or None to disable auth
2756    :param list client_names: client names (1-16 characters "A-Za-z0-9+-_")
2757
2758    :returns: :class:`~stem.cotroller.CreateHiddenServiceOutput` if we create
2759      or update a hidden service, **None** otherwise
2760
2761    :raises: :class:`stem.ControllerError` if the call fails
2762    """
2763
2764    if not stem.util.connection.is_valid_port(port):
2765      raise ValueError("%s isn't a valid port number" % port)
2766    elif target_address and not stem.util.connection.is_valid_ipv4_address(target_address):
2767      raise ValueError("%s isn't a valid IPv4 address" % target_address)
2768    elif target_port is not None and not stem.util.connection.is_valid_port(target_port):
2769      raise ValueError("%s isn't a valid port number" % target_port)
2770    elif auth_type not in (None, 'basic', 'stealth'):
2771      raise ValueError("%s isn't a recognized type of authentication" % auth_type)
2772
2773    port = int(port)
2774    target_address = target_address if target_address else '127.0.0.1'
2775    target_port = port if target_port is None else int(target_port)
2776
2777    conf = self.get_hidden_service_conf()
2778
2779    if path in conf and (port, target_address, target_port) in conf[path]['HiddenServicePort']:
2780      return None
2781
2782    conf.setdefault(path, OrderedDict()).setdefault('HiddenServicePort', []).append((port, target_address, target_port))
2783
2784    if auth_type and client_names:
2785      hsac = "%s %s" % (auth_type, ','.join(client_names))
2786      conf[path]['HiddenServiceAuthorizeClient'] = hsac
2787
2788    # Tor 0.3.5 changes its default for HS creation from v2 to v3. This is
2789    # fine, but there's a couple options that are incompatible with v3. If
2790    # creating a service with one of those we should explicitly create a v2
2791    # service instead.
2792    #
2793    #   https://trac.torproject.org/projects/tor/ticket/27446
2794
2795    for path in conf:
2796      if 'HiddenServiceAuthorizeClient' in conf[path] or 'RendPostPeriod' in conf[path]:
2797        conf[path]['HiddenServiceVersion'] = '2'
2798
2799    self.set_hidden_service_conf(conf)
2800
2801    hostname, hostname_for_client = None, {}
2802
2803    if self.is_localhost():
2804      hostname_path = os.path.join(path, 'hostname')
2805
2806      if not os.path.isabs(hostname_path):
2807        cwd = stem.util.system.cwd(self.get_pid(None))
2808
2809        if cwd:
2810          hostname_path = stem.util.system.expand_path(hostname_path, cwd)
2811
2812      if os.path.isabs(hostname_path):
2813        start_time = time.time()
2814
2815        while not os.path.exists(hostname_path):
2816          wait_time = time.time() - start_time
2817
2818          if wait_time >= 3:
2819            break
2820          else:
2821            time.sleep(0.05)
2822
2823        try:
2824          with open(hostname_path) as hostname_file:
2825            hostname = hostname_file.read().strip()
2826
2827            if client_names and '\n' in hostname:
2828              # When there's multiple clients this looks like...
2829              #
2830              # ndisjxzkgcdhrwqf.onion sjUwjTSPznqWLdOPuwRUzg # client: c1
2831              # ndisjxzkgcdhrwqf.onion sUu92axuL5bKnA76s2KRfw # client: c2
2832
2833              for line in hostname.splitlines():
2834                if ' # client: ' in line:
2835                  address = line.split()[0]
2836                  client = line.split(' # client: ', 1)[1]
2837
2838                  if len(address) == 22 and address.endswith('.onion'):
2839                    hostname_for_client[client] = address
2840        except:
2841          pass
2842
2843    return CreateHiddenServiceOutput(
2844      path = path,
2845      hostname = hostname,
2846      hostname_for_client = hostname_for_client,
2847      config = conf,
2848    )
2849
2850  def remove_hidden_service(self, path, port = None):
2851    """
2852    Discontinues a given hidden service.
2853
2854    .. versionadded:: 1.3.0
2855
2856    :param str path: path for the hidden service's data directory
2857    :param int port: hidden service port
2858
2859    :returns: **True** if the hidden service is discontinued, **False** if it
2860      wasn't running in the first place
2861
2862    :raises: :class:`stem.ControllerError` if the call fails
2863    """
2864
2865    if port and not stem.util.connection.is_valid_port(port):
2866      raise ValueError("%s isn't a valid port number" % port)
2867
2868    port = int(port) if port else None
2869    conf = self.get_hidden_service_conf()
2870
2871    if path not in conf:
2872      return False
2873
2874    if not port:
2875      del conf[path]
2876    else:
2877      to_remove = [entry for entry in conf[path]['HiddenServicePort'] if entry[0] == port]
2878
2879      if not to_remove:
2880        return False
2881
2882      for entry in to_remove:
2883        conf[path]['HiddenServicePort'].remove(entry)
2884
2885      if not conf[path]['HiddenServicePort']:
2886        del conf[path]  # no ports left
2887
2888    self.set_hidden_service_conf(conf)
2889    return True
2890
2891  @with_default()
2892  def list_ephemeral_hidden_services(self, default = UNDEFINED, our_services = True, detached = False):
2893    """
2894    list_ephemeral_hidden_services(default = UNDEFINED, our_services = True, detached = False)
2895
2896    Lists hidden service addresses created by
2897    :func:`~stem.control.Controller.create_ephemeral_hidden_service`.
2898
2899    .. versionadded:: 1.4.0
2900
2901    .. versionchanged:: 1.6.0
2902       Tor change caused this to start providing empty strings if unset
2903       (:trac:`21329`).
2904
2905    :param object default: response if the query fails
2906    :param bool our_services: include services created with this controller
2907      that weren't flagged as 'detached'
2908    :param bool detached: include services whos contiuation isn't tied to a
2909      controller
2910
2911    :returns: **list** of hidden service addresses without their '.onion'
2912      suffix
2913
2914    :raises: :class:`stem.ControllerError` if the call fails and we weren't
2915      provided a default response
2916    """
2917
2918    if self.get_version() < stem.version.Requirement.ADD_ONION:
2919      raise stem.UnsatisfiableRequest(message = 'Ephemeral hidden services were added in tor version %s' % stem.version.Requirement.ADD_ONION)
2920
2921    result = []
2922
2923    if our_services:
2924      try:
2925        result += self.get_info('onions/current').split('\n')
2926      except (stem.ProtocolError, stem.OperationFailed) as exc:
2927        # TODO: Tor's behavior around this was changed in Feb 2017, we should
2928        # drop it when all versions that did this are deprecated...
2929        #
2930        #   https://trac.torproject.org/projects/tor/ticket/21329
2931
2932        if 'No onion services of the specified type.' not in str(exc):
2933          raise
2934
2935    if detached:
2936      try:
2937        result += self.get_info('onions/detached').split('\n')
2938      except (stem.ProtocolError, stem.OperationFailed) as exc:
2939        if 'No onion services of the specified type.' not in str(exc):
2940          raise
2941
2942    return [r for r in result if r]  # drop any empty responses (GETINFO is blank if unset)
2943
2944  def create_ephemeral_hidden_service(self, ports, key_type = 'NEW', key_content = 'BEST', discard_key = False, detached = False, await_publication = False, timeout = None, basic_auth = None, max_streams = None):
2945    """
2946    Creates a new hidden service. Unlike
2947    :func:`~stem.control.Controller.create_hidden_service` this style of
2948    hidden service doesn't touch disk, carrying with it a lot of advantages.
2949    This is the suggested method for making hidden services.
2950
2951    Our **ports** argument can be a single port...
2952
2953    ::
2954
2955      create_ephemeral_hidden_service(80)
2956
2957    ... list of ports the service is available on...
2958
2959    ::
2960
2961      create_ephemeral_hidden_service([80, 443])
2962
2963    ... or a mapping of hidden service ports to their targets...
2964
2965    ::
2966
2967      create_ephemeral_hidden_service({80: 80, 443: '173.194.33.133:443'})
2968
2969    If **basic_auth** is provided this service will require basic
2970    authentication to access. This means users must set HidServAuth in their
2971    torrc with credentials to access it.
2972
2973    **basic_auth** is a mapping of usernames to their credentials. If the
2974    credential is **None** one is generated and returned as part of the
2975    response. For instance, only bob can access using the given newly generated
2976    credentials...
2977
2978    ::
2979
2980      >>> response = controller.create_ephemeral_hidden_service(80, basic_auth = {'bob': None})
2981      >>> print(response.client_auth)
2982      {'bob': 'nKwfvVPmTNr2k2pG0pzV4g'}
2983
2984    ... while both alice and bob can access with existing credentials in the
2985    following...
2986
2987    ::
2988
2989      controller.create_ephemeral_hidden_service(80, basic_auth = {
2990        'alice': 'l4BT016McqV2Oail+Bwe6w',
2991        'bob': 'vGnNRpWYiMBFTWD2gbBlcA',
2992      })
2993
2994    To create a **version 3** service simply specify **ED25519-V3** as the
2995    our key type, and to create a **version 2** service use **RSA1024**. The
2996    default version of newly created hidden services is based on the
2997    **HiddenServiceVersion** value in your torrc...
2998
2999    ::
3000
3001      response = controller.create_ephemeral_hidden_service(
3002        80,
3003        key_content = 'ED25519-V3',
3004        await_publication = True,
3005      )
3006
3007      print('service established at %s.onion' % response.service_id)
3008
3009    .. versionadded:: 1.4.0
3010
3011    .. versionchanged:: 1.5.0
3012       Added the basic_auth argument.
3013
3014    .. versionchanged:: 1.5.0
3015       Added support for non-anonymous services. To do so set
3016       'HiddenServiceSingleHopMode 1' and 'HiddenServiceNonAnonymousMode 1' in
3017       your torrc.
3018
3019    .. versionchanged:: 1.7.0
3020       Added the timeout and max_streams arguments.
3021
3022    :param int,list,dict ports: hidden service port(s) or mapping of hidden
3023      service ports to their targets
3024    :param str key_type: type of key being provided, generates a new key if
3025      'NEW' (options are: **NEW**, **RSA1024**, and **ED25519-V3**)
3026    :param str key_content: key for the service to use or type of key to be
3027      generated (options when **key_type** is **NEW** are **BEST**,
3028      **RSA1024**, and **ED25519-V3**)
3029    :param bool discard_key: avoid providing the key back in our response
3030    :param bool detached: continue this hidden service even after this control
3031      connection is closed if **True**
3032    :param bool await_publication: blocks until our descriptor is successfully
3033      published if **True**
3034    :param float timeout: seconds to wait when **await_result** is **True**
3035    :param dict basic_auth: required user credentials to access this service
3036    :param int max_streams: maximum number of streams the hidden service will
3037      accept, unlimited if zero or not set
3038
3039    :returns: :class:`~stem.response.add_onion.AddOnionResponse` with the response
3040
3041    :raises:
3042      * :class:`stem.ControllerError` if the call fails
3043      * :class:`stem.Timeout` if **timeout** was reached
3044    """
3045
3046    if self.get_version() < stem.version.Requirement.ADD_ONION:
3047      raise stem.UnsatisfiableRequest(message = 'Ephemeral hidden services were added in tor version %s' % stem.version.Requirement.ADD_ONION)
3048
3049    hs_desc_queue, hs_desc_listener = queue.Queue(), None
3050    start_time = time.time()
3051
3052    if await_publication:
3053      def hs_desc_listener(event):
3054        hs_desc_queue.put(event)
3055
3056      self.add_event_listener(hs_desc_listener, EventType.HS_DESC)
3057
3058    request = 'ADD_ONION %s:%s' % (key_type, key_content)
3059
3060    flags = []
3061
3062    if discard_key:
3063      flags.append('DiscardPK')
3064
3065    if detached:
3066      flags.append('Detach')
3067
3068    if basic_auth is not None:
3069      if self.get_version() < stem.version.Requirement.ADD_ONION_BASIC_AUTH:
3070        raise stem.UnsatisfiableRequest(message = 'Basic authentication support was added to ADD_ONION in tor version %s' % stem.version.Requirement.ADD_ONION_BASIC_AUTH)
3071
3072      flags.append('BasicAuth')
3073
3074    if max_streams is not None:
3075      if self.get_version() < stem.version.Requirement.ADD_ONION_MAX_STREAMS:
3076        raise stem.UnsatisfiableRequest(message = 'Limitation of the maximum number of streams to accept was added to ADD_ONION in tor version %s' % stem.version.Requirement.ADD_ONION_MAX_STREAMS)
3077
3078      flags.append('MaxStreamsCloseCircuit')
3079
3080    if self.get_version() >= stem.version.Requirement.ADD_ONION_NON_ANONYMOUS:
3081      if self.get_conf('HiddenServiceSingleHopMode', None) == '1' and self.get_conf('HiddenServiceNonAnonymousMode', None) == '1':
3082        flags.append('NonAnonymous')
3083
3084    if flags:
3085      request += ' Flags=%s' % ','.join(flags)
3086
3087    if max_streams is not None:
3088      request += ' MaxStreams=%s' % max_streams
3089
3090    if isinstance(ports, int):
3091      request += ' Port=%s' % ports
3092    elif isinstance(ports, list):
3093      for port in ports:
3094        request += ' Port=%s' % port
3095    elif isinstance(ports, dict):
3096      for port, target in ports.items():
3097        request += ' Port=%s,%s' % (port, target)
3098    else:
3099      raise ValueError("The 'ports' argument of create_ephemeral_hidden_service() needs to be an int, list, or dict")
3100
3101    if basic_auth is not None:
3102      for client_name, client_blob in basic_auth.items():
3103        if client_blob:
3104          request += ' ClientAuth=%s:%s' % (client_name, client_blob)
3105        else:
3106          request += ' ClientAuth=%s' % client_name
3107
3108    response = self.msg(request)
3109    stem.response.convert('ADD_ONION', response)
3110
3111    if await_publication:
3112      # We should receive five UPLOAD events, followed by up to another five
3113      # UPLOADED to indicate they've finished. Presently tor seems to have an
3114      # issue where the address is provided for UPLOAD but not UPLOADED so need
3115      # to just guess that if it's for the same hidden service authority then
3116      # it's what we're looking for.
3117
3118      directories_uploaded_to, failures = [], []
3119
3120      try:
3121        while True:
3122          event = _get_with_timeout(hs_desc_queue, timeout, start_time)
3123
3124          if event.action == stem.HSDescAction.UPLOAD and event.address == response.service_id:
3125            directories_uploaded_to.append(event.directory_fingerprint)
3126          elif event.action == stem.HSDescAction.UPLOADED and event.directory_fingerprint in directories_uploaded_to:
3127            break  # successfully uploaded to a HS authority... maybe
3128          elif event.action == stem.HSDescAction.FAILED and event.directory_fingerprint in directories_uploaded_to:
3129            failures.append('%s (%s)' % (event.directory_fingerprint, event.reason))
3130
3131            if len(directories_uploaded_to) == len(failures):
3132              raise stem.OperationFailed(message = 'Failed to upload our hidden service descriptor to %s' % ', '.join(failures))
3133      finally:
3134        self.remove_event_listener(hs_desc_listener)
3135
3136    return response
3137
3138  def remove_ephemeral_hidden_service(self, service_id):
3139    """
3140    Discontinues a given hidden service that was created with
3141    :func:`~stem.control.Controller.create_ephemeral_hidden_service`.
3142
3143    .. versionadded:: 1.4.0
3144
3145    :param str service_id: hidden service address without the '.onion' suffix
3146
3147    :returns: **True** if the hidden service is discontinued, **False** if it
3148      wasn't running in the first place
3149
3150    :raises: :class:`stem.ControllerError` if the call fails
3151    """
3152
3153    if self.get_version() < stem.version.Requirement.ADD_ONION:
3154      raise stem.UnsatisfiableRequest(message = 'Ephemeral hidden services were added in tor version %s' % stem.version.Requirement.ADD_ONION)
3155
3156    response = self.msg('DEL_ONION %s' % service_id)
3157    stem.response.convert('SINGLELINE', response)
3158
3159    if response.is_ok():
3160      return True
3161    elif response.code == '552':
3162      return False  # no hidden service to discontinue
3163    else:
3164      raise stem.ProtocolError('DEL_ONION returned unexpected response code: %s' % response.code)
3165
3166  def add_event_listener(self, listener, *events):
3167    """
3168    Directs further tor controller events to a given function. The function is
3169    expected to take a single argument, which is a
3170    :class:`~stem.response.events.Event` subclass. For instance the following
3171    would print the bytes sent and received by tor over five seconds...
3172
3173    ::
3174
3175      import time
3176      from stem.control import Controller, EventType
3177
3178      def print_bw(event):
3179        print('sent: %i, received: %i' % (event.written, event.read))
3180
3181      with Controller.from_port(port = 9051) as controller:
3182        controller.authenticate()
3183        controller.add_event_listener(print_bw, EventType.BW)
3184        time.sleep(5)
3185
3186    If a new control connection is initialized then this listener will be
3187    reattached.
3188
3189    If tor emits a malformed event it can be received by listening for the
3190    stem.control.MALFORMED_EVENTS constant.
3191
3192    .. versionchanged:: 1.7.0
3193       Listener exceptions and malformed events no longer break further event
3194       processing. Added the **MALFORMED_EVENTS** constant.
3195
3196    :param functor listener: function to be called when an event is received
3197    :param stem.control.EventType events: event types to be listened for
3198
3199    :raises: :class:`stem.ProtocolError` if unable to set the events
3200    """
3201
3202    # first checking that tor supports these event types
3203
3204    with self._event_listeners_lock:
3205      if self.is_authenticated():
3206        for event_type in events:
3207          event_type = stem.response.events.EVENT_TYPE_TO_CLASS.get(event_type)
3208
3209          if event_type and (self.get_version() < event_type._VERSION_ADDED):
3210            raise stem.InvalidRequest(552, '%s event requires Tor version %s or later' % (event_type, event_type._VERSION_ADDED))
3211
3212      for event_type in events:
3213        self._event_listeners.setdefault(event_type, []).append(listener)
3214
3215      failed_events = self._attach_listeners()[1]
3216
3217      # restricted the failures to just things we requested
3218
3219      failed_events = set(failed_events).intersection(set(events))
3220
3221      if failed_events:
3222        raise stem.ProtocolError('SETEVENTS rejected %s' % ', '.join(failed_events))
3223
3224  def remove_event_listener(self, listener):
3225    """
3226    Stops a listener from being notified of further tor events.
3227
3228    :param stem.control.EventListener listener: listener to be removed
3229
3230    :raises: :class:`stem.ProtocolError` if unable to set the events
3231    """
3232
3233    with self._event_listeners_lock:
3234      event_types_changed = False
3235
3236      for event_type, event_listeners in list(self._event_listeners.items()):
3237        if listener in event_listeners:
3238          event_listeners.remove(listener)
3239
3240          if len(event_listeners) == 0:
3241            event_types_changed = True
3242            del self._event_listeners[event_type]
3243
3244      if event_types_changed:
3245        response = self.msg('SETEVENTS %s' % ' '.join(self._event_listeners.keys()))
3246
3247        if not response.is_ok():
3248          raise stem.ProtocolError('SETEVENTS received unexpected response\n%s' % response)
3249
3250  def _get_cache(self, param, namespace = None):
3251    """
3252    Queries our request cache for the given key.
3253
3254    :param str param: key to be queried
3255    :param str namespace: namespace in which to check for the key
3256
3257    :returns: cached value corresponding to key or **None** if the key wasn't found
3258    """
3259
3260    with self._cache_lock:
3261      if not self.is_caching_enabled():
3262        return None
3263
3264      cache_key = '%s.%s' % (namespace, param) if namespace else param
3265      return self._request_cache.get(cache_key, None)
3266
3267  def _get_cache_map(self, params, namespace = None):
3268    """
3269    Queries our request cache for multiple entries.
3270
3271    :param list params: keys to be queried
3272    :param str namespace: namespace in which to check for the keys
3273
3274    :returns: **dict** of 'param => cached value' pairs of keys present in cache
3275    """
3276
3277    with self._cache_lock:
3278      cached_values = {}
3279
3280      if self.is_caching_enabled():
3281        for param in params:
3282          cache_key = '%s.%s' % (namespace, param) if namespace else param
3283
3284          if cache_key in self._request_cache:
3285            cached_values[param] = self._request_cache[cache_key]
3286
3287      return cached_values
3288
3289  def _set_cache(self, params, namespace = None):
3290    """
3291    Sets the given request cache entries. If the new cache value is **None**
3292    then it is removed from our cache.
3293
3294    :param dict params: **dict** of 'cache_key => value' pairs to be cached
3295    :param str namespace: namespace for the keys
3296    """
3297
3298    with self._cache_lock:
3299      if not self.is_caching_enabled():
3300        return
3301
3302      # if params is None then clear the namespace
3303
3304      if params is None and namespace:
3305        for cache_key in list(self._request_cache.keys()):
3306          if cache_key.startswith('%s.' % namespace):
3307            del self._request_cache[cache_key]
3308
3309        return
3310
3311      # remove uncacheable items
3312      if namespace == 'getconf':
3313        # shallow copy before edit so as not to change it for the caller
3314        params = params.copy()
3315        for key in UNCACHEABLE_GETCONF_PARAMS:
3316          if key in params:
3317            del params[key]
3318
3319      for key, value in list(params.items()):
3320        if namespace:
3321          cache_key = '%s.%s' % (namespace, key)
3322        else:
3323          cache_key = key
3324
3325        if value is None:
3326          if cache_key in list(self._request_cache.keys()):
3327            del self._request_cache[cache_key]
3328        else:
3329          self._request_cache[cache_key] = value
3330
3331  def _confchanged_cache_invalidation(self, params):
3332    """
3333    Drops dependent portions of the cache when configuration changes.
3334
3335    :param dict params: **dict** of 'config_key => value' pairs for configs
3336      that changed. The entries' values are currently unused.
3337    """
3338
3339    with self._cache_lock:
3340      if not self.is_caching_enabled():
3341        return
3342
3343      if any('hidden' in param.lower() for param in params.keys()):
3344        self._set_cache({'hidden_service_conf': None})
3345
3346      # reset any getinfo parameters that can be changed by a SETCONF
3347
3348      self._set_cache(dict([(k.lower(), None) for k in CACHEABLE_GETINFO_PARAMS_UNTIL_SETCONF]), 'getinfo')
3349      self._set_cache(None, 'listeners')
3350
3351      self._set_cache({'get_custom_options': None})
3352
3353      self._set_cache({'exit_policy': None})  # numerous options can change our policy
3354
3355  def is_caching_enabled(self):
3356    """
3357    **True** if caching has been enabled, **False** otherwise.
3358
3359    :returns: bool to indicate if caching is enabled
3360    """
3361
3362    return self._is_caching_enabled
3363
3364  def set_caching(self, enabled):
3365    """
3366    Enables or disables caching of information retrieved from tor.
3367
3368    :param bool enabled: **True** to enable caching, **False** to disable it
3369    """
3370
3371    self._is_caching_enabled = enabled
3372
3373    if not self._is_caching_enabled:
3374      self.clear_cache()
3375
3376  def clear_cache(self):
3377    """
3378    Drops any cached results.
3379    """
3380
3381    with self._cache_lock:
3382      self._request_cache = {}
3383      self._last_newnym = 0.0
3384      self._is_geoip_unavailable = None
3385
3386  def load_conf(self, configtext):
3387    """
3388    Sends the configuration text to Tor and loads it as if it has been read from
3389    the torrc.
3390
3391    :param str configtext: the configuration text
3392
3393    :raises: :class:`stem.ControllerError` if the call fails
3394    """
3395
3396    response = self.msg('LOADCONF\n%s' % configtext)
3397    stem.response.convert('SINGLELINE', response)
3398
3399    if response.code in ('552', '553'):
3400      if response.code == '552' and response.message.startswith('Invalid config file: Failed to parse/validate config: Unknown option'):
3401        raise stem.InvalidArguments(response.code, response.message, [response.message[70:response.message.find('.', 70) - 1]])
3402      raise stem.InvalidRequest(response.code, response.message)
3403    elif not response.is_ok():
3404      raise stem.ProtocolError('+LOADCONF Received unexpected response\n%s' % str(response))
3405
3406  def save_conf(self, force = False):
3407    """
3408    Saves the current configuration options into the active torrc file.
3409
3410    .. versionchanged:: 1.6.0
3411       Added the force argument.
3412
3413    :param bool force: overwrite the configuration even if it includes a
3414      '%include' clause, this is ignored if tor doesn't support it
3415
3416    :raises:
3417      * :class:`stem.ControllerError` if the call fails
3418      * :class:`stem.OperationFailed` if the client is unable to save
3419        the configuration file
3420    """
3421
3422    if self.get_version() < stem.version.Requirement.SAVECONF_FORCE:
3423      force = False
3424
3425    response = self.msg('SAVECONF FORCE' if force else 'SAVECONF')
3426    stem.response.convert('SINGLELINE', response)
3427
3428    if response.is_ok():
3429      return True
3430    elif response.code == '551':
3431      raise stem.OperationFailed(response.code, response.message)
3432    else:
3433      raise stem.ProtocolError('SAVECONF returned unexpected response code')
3434
3435  def is_feature_enabled(self, feature):
3436    """
3437    Checks if a control connection feature is enabled. These features can be
3438    enabled using :func:`~stem.control.Controller.enable_feature`.
3439
3440    :param str feature: feature to be checked
3441
3442    :returns: **True** if feature is enabled, **False** otherwise
3443    """
3444
3445    feature = feature.upper()
3446
3447    if feature in self._enabled_features:
3448      return True
3449    else:
3450      # check if this feature is on by default
3451      defaulted_version = None
3452
3453      if feature == 'EXTENDED_EVENTS':
3454        defaulted_version = stem.version.Requirement.FEATURE_EXTENDED_EVENTS
3455      elif feature == 'VERBOSE_NAMES':
3456        defaulted_version = stem.version.Requirement.FEATURE_VERBOSE_NAMES
3457
3458      if defaulted_version:
3459        our_version = self.get_version(None)
3460
3461        if our_version and our_version >= defaulted_version:
3462          self._enabled_features.append(feature)
3463
3464      return feature in self._enabled_features
3465
3466  def enable_feature(self, features):
3467    """
3468    Enables features that are disabled by default to maintain backward
3469    compatibility. Once enabled, a feature cannot be disabled and a new
3470    control connection must be opened to get a connection with the feature
3471    disabled. Feature names are case-insensitive.
3472
3473    The following features are currently accepted:
3474
3475      * EXTENDED_EVENTS - Requests the extended event syntax
3476      * VERBOSE_NAMES - Replaces ServerID with LongName in events and GETINFO results
3477
3478    :param str,list features: a single feature or a list of features to be enabled
3479
3480    :raises:
3481      * :class:`stem.ControllerError` if the call fails
3482      * :class:`stem.InvalidArguments` if features passed were invalid
3483    """
3484
3485    if stem.util._is_str(features):
3486      features = [features]
3487
3488    response = self.msg('USEFEATURE %s' % ' '.join(features))
3489    stem.response.convert('SINGLELINE', response)
3490
3491    if not response.is_ok():
3492      if response.code == '552':
3493        invalid_feature = []
3494
3495        if response.message.startswith('Unrecognized feature "'):
3496          invalid_feature = [response.message[22:response.message.find('"', 22)]]
3497
3498        raise stem.InvalidArguments(response.code, response.message, invalid_feature)
3499
3500      raise stem.ProtocolError('USEFEATURE provided an invalid response code: %s' % response.code)
3501
3502    self._enabled_features += [entry.upper() for entry in features]
3503
3504  @with_default()
3505  def get_circuit(self, circuit_id, default = UNDEFINED):
3506    """
3507    get_circuit(circuit_id, default = UNDEFINED)
3508
3509    Provides a circuit currently available from tor.
3510
3511    :param int circuit_id: circuit to be fetched
3512    :param object default: response if the query fails
3513
3514    :returns: :class:`stem.response.events.CircuitEvent` for the given circuit
3515
3516    :raises:
3517      * :class:`stem.ControllerError` if the call fails
3518      * **ValueError** if the circuit doesn't exist
3519
3520      An exception is only raised if we weren't provided a default response.
3521    """
3522
3523    for circ in self.get_circuits():
3524      if circ.id == circuit_id:
3525        return circ
3526
3527    raise ValueError("Tor currently does not have a circuit with the id of '%s'" % circuit_id)
3528
3529  @with_default()
3530  def get_circuits(self, default = UNDEFINED):
3531    """
3532    get_circuits(default = UNDEFINED)
3533
3534    Provides tor's currently available circuits.
3535
3536    :param object default: response if the query fails
3537
3538    :returns: **list** of :class:`stem.response.events.CircuitEvent` for our circuits
3539
3540    :raises: :class:`stem.ControllerError` if the call fails and no default was provided
3541    """
3542
3543    circuits = []
3544    response = self.get_info('circuit-status')
3545
3546    for circ in response.splitlines():
3547      circ_message = stem.socket.recv_message(io.BytesIO(stem.util.str_tools._to_bytes('650 CIRC %s\r\n' % circ)))
3548      stem.response.convert('EVENT', circ_message)
3549      circuits.append(circ_message)
3550
3551    return circuits
3552
3553  def new_circuit(self, path = None, purpose = 'general', await_build = False, timeout = None):
3554    """
3555    Requests a new circuit. If the path isn't provided, one is automatically
3556    selected.
3557
3558    .. versionchanged:: 1.7.0
3559       Added the timeout argument.
3560
3561    :param list,str path: one or more relays to make a circuit through
3562    :param str purpose: 'general' or 'controller'
3563    :param bool await_build: blocks until the circuit is built if **True**
3564    :param float timeout: seconds to wait when **await_build** is **True**
3565
3566    :returns: str of the circuit id of the newly created circuit
3567
3568    :raises:
3569      * :class:`stem.ControllerError` if the call fails
3570      * :class:`stem.Timeout` if **timeout** was reached
3571    """
3572
3573    return self.extend_circuit('0', path, purpose, await_build, timeout)
3574
3575  def extend_circuit(self, circuit_id = '0', path = None, purpose = 'general', await_build = False, timeout = None):
3576    """
3577    Either requests the creation of a new circuit or extends an existing one.
3578
3579    When called with a circuit value of zero (the default) a new circuit is
3580    created, and when non-zero the circuit with that id is extended. If the
3581    path isn't provided, one is automatically selected.
3582
3583    A python interpreter session used to create circuits could look like this...
3584
3585    ::
3586
3587      >>> controller.extend_circuit('0', ['718BCEA286B531757ACAFF93AE04910EA73DE617', '30BAB8EE7606CBD12F3CC269AE976E0153E7A58D', '2765D8A8C4BBA3F89585A9FFE0E8575615880BEB'])
3588      19
3589      >>> controller.extend_circuit('0')
3590      20
3591      >>> print(controller.get_info('circuit-status'))
3592      20 EXTENDED $718BCEA286B531757ACAFF93AE04910EA73DE617=KsmoinOK,$649F2D0ACF418F7CFC6539AB2257EB2D5297BAFA=Eskimo BUILD_FLAGS=NEED_CAPACITY PURPOSE=GENERAL TIME_CREATED=2012-12-06T13:51:11.433755
3593      19 BUILT $718BCEA286B531757ACAFF93AE04910EA73DE617=KsmoinOK,$30BAB8EE7606CBD12F3CC269AE976E0153E7A58D=Pascal1,$2765D8A8C4BBA3F89585A9FFE0E8575615880BEB=Anthracite PURPOSE=GENERAL TIME_CREATED=2012-12-06T13:50:56.969938
3594
3595    .. versionchanged:: 1.7.0
3596       Added the timeout argument.
3597
3598    :param str circuit_id: id of a circuit to be extended
3599    :param list,str path: one or more relays to make a circuit through, this is
3600      required if the circuit id is non-zero
3601    :param str purpose: 'general' or 'controller'
3602    :param bool await_build: blocks until the circuit is built if **True**
3603    :param float timeout: seconds to wait when **await_build** is **True**
3604
3605    :returns: str of the circuit id of the created or extended circuit
3606
3607    :raises:
3608      * :class:`stem.InvalidRequest` if one of the parameters were invalid
3609      * :class:`stem.CircuitExtensionFailed` if we were waiting for the circuit
3610        to build but it failed
3611      * :class:`stem.Timeout` if **timeout** was reached
3612      * :class:`stem.ControllerError` if the call fails
3613    """
3614
3615    # Attaches a temporary listener for CIRC events if we'll be waiting for it
3616    # to build. This is icky, but we can't reliably do this via polling since
3617    # we then can't get the failure if it can't be created.
3618
3619    circ_queue, circ_listener = queue.Queue(), None
3620    start_time = time.time()
3621
3622    if await_build:
3623      def circ_listener(event):
3624        circ_queue.put(event)
3625
3626      self.add_event_listener(circ_listener, EventType.CIRC)
3627
3628    try:
3629      # we might accidently get integer circuit ids
3630      circuit_id = str(circuit_id)
3631
3632      if path is None and circuit_id == '0':
3633        path_opt_version = stem.version.Requirement.EXTENDCIRCUIT_PATH_OPTIONAL
3634
3635        if not self.get_version() >= path_opt_version:
3636          raise stem.InvalidRequest(512, 'EXTENDCIRCUIT requires the path prior to version %s' % path_opt_version)
3637
3638      args = [circuit_id]
3639
3640      if stem.util._is_str(path):
3641        path = [path]
3642
3643      if path:
3644        args.append(','.join(path))
3645
3646      if purpose:
3647        args.append('purpose=%s' % purpose)
3648
3649      response = self.msg('EXTENDCIRCUIT %s' % ' '.join(args))
3650      stem.response.convert('SINGLELINE', response)
3651
3652      if response.code in ('512', '552'):
3653        raise stem.InvalidRequest(response.code, response.message)
3654      elif not response.is_ok():
3655        raise stem.ProtocolError('EXTENDCIRCUIT returned unexpected response code: %s' % response.code)
3656
3657      if not response.message.startswith('EXTENDED '):
3658        raise stem.ProtocolError('EXTENDCIRCUIT response invalid:\n%s', response)
3659
3660      new_circuit = response.message.split(' ', 1)[1]
3661
3662      if await_build:
3663        while True:
3664          circ = _get_with_timeout(circ_queue, timeout, start_time)
3665
3666          if circ.id == new_circuit:
3667            if circ.status == CircStatus.BUILT:
3668              break
3669            elif circ.status == CircStatus.FAILED:
3670              raise stem.CircuitExtensionFailed('Circuit failed to be created: %s' % circ.reason, circ)
3671            elif circ.status == CircStatus.CLOSED:
3672              raise stem.CircuitExtensionFailed('Circuit was closed prior to build', circ)
3673
3674      return new_circuit
3675    finally:
3676      if circ_listener:
3677        self.remove_event_listener(circ_listener)
3678
3679  def repurpose_circuit(self, circuit_id, purpose):
3680    """
3681    Changes a circuit's purpose. Currently, two purposes are recognized...
3682      * general
3683      * controller
3684
3685    :param str circuit_id: id of the circuit whose purpose is to be changed
3686    :param str purpose: purpose (either 'general' or 'controller')
3687
3688    :raises: :class:`stem.InvalidArguments` if the circuit doesn't exist or if the purpose was invalid
3689    """
3690
3691    response = self.msg('SETCIRCUITPURPOSE %s purpose=%s' % (circuit_id, purpose))
3692    stem.response.convert('SINGLELINE', response)
3693
3694    if not response.is_ok():
3695      if response.code == '552':
3696        raise stem.InvalidRequest(response.code, response.message)
3697      else:
3698        raise stem.ProtocolError('SETCIRCUITPURPOSE returned unexpected response code: %s' % response.code)
3699
3700  def close_circuit(self, circuit_id, flag = ''):
3701    """
3702    Closes the specified circuit.
3703
3704    :param str circuit_id: id of the circuit to be closed
3705    :param str flag: optional value to modify closing, the only flag available
3706      is 'IfUnused' which will not close the circuit unless it is unused
3707
3708    :raises: :class:`stem.InvalidArguments` if the circuit is unknown
3709    :raises: :class:`stem.InvalidRequest` if not enough information is provided
3710    """
3711
3712    response = self.msg('CLOSECIRCUIT %s %s' % (circuit_id, flag))
3713    stem.response.convert('SINGLELINE', response)
3714
3715    if not response.is_ok():
3716      if response.code in ('512', '552'):
3717        if response.message.startswith('Unknown circuit '):
3718          raise stem.InvalidArguments(response.code, response.message, [circuit_id])
3719        raise stem.InvalidRequest(response.code, response.message)
3720      else:
3721        raise stem.ProtocolError('CLOSECIRCUIT returned unexpected response code: %s' % response.code)
3722
3723  @with_default()
3724  def get_streams(self, default = UNDEFINED):
3725    """
3726    get_streams(default = UNDEFINED)
3727
3728    Provides the list of streams tor is currently handling.
3729
3730    :param object default: response if the query fails
3731
3732    :returns: list of :class:`stem.response.events.StreamEvent` objects
3733
3734    :raises: :class:`stem.ControllerError` if the call fails and no default was
3735      provided
3736    """
3737
3738    streams = []
3739    response = self.get_info('stream-status')
3740
3741    for stream in response.splitlines():
3742      message = stem.socket.recv_message(io.BytesIO(stem.util.str_tools._to_bytes('650 STREAM %s\r\n' % stream)))
3743      stem.response.convert('EVENT', message)
3744      streams.append(message)
3745
3746    return streams
3747
3748  def attach_stream(self, stream_id, circuit_id, exiting_hop = None):
3749    """
3750    Attaches a stream to a circuit.
3751
3752    Note: Tor attaches streams to circuits automatically unless the
3753    __LeaveStreamsUnattached configuration variable is set to '1'
3754
3755    :param str stream_id: id of the stream that must be attached
3756    :param str circuit_id: id of the circuit to which it must be attached
3757    :param int exiting_hop: hop in the circuit where traffic should exit
3758
3759    :raises:
3760      * :class:`stem.InvalidRequest` if the stream or circuit id were unrecognized
3761      * :class:`stem.UnsatisfiableRequest` if the stream isn't in a state where it can be attached
3762      * :class:`stem.OperationFailed` if the stream couldn't be attached for any other reason
3763    """
3764
3765    query = 'ATTACHSTREAM %s %s' % (stream_id, circuit_id)
3766
3767    if exiting_hop:
3768      query += ' HOP=%s' % exiting_hop
3769
3770    response = self.msg(query)
3771    stem.response.convert('SINGLELINE', response)
3772
3773    if not response.is_ok():
3774      if response.code == '552':
3775        raise stem.InvalidRequest(response.code, response.message)
3776      elif response.code == '551':
3777        raise stem.OperationFailed(response.code, response.message)
3778      elif response.code == '555':
3779        raise stem.UnsatisfiableRequest(response.code, response.message)
3780      else:
3781        raise stem.ProtocolError('ATTACHSTREAM returned unexpected response code: %s' % response.code)
3782
3783  def close_stream(self, stream_id, reason = stem.RelayEndReason.MISC, flag = ''):
3784    """
3785    Closes the specified stream.
3786
3787    :param str stream_id: id of the stream to be closed
3788    :param stem.RelayEndReason reason: reason the stream is closing
3789    :param str flag: not currently used
3790
3791    :raises:
3792      * :class:`stem.InvalidArguments` if the stream or reason are not recognized
3793      * :class:`stem.InvalidRequest` if the stream and/or reason are missing
3794    """
3795
3796    # there's a single value offset between RelayEndReason.index_of() and the
3797    # value that tor expects since tor's value starts with the index of one
3798
3799    response = self.msg('CLOSESTREAM %s %s %s' % (stream_id, stem.RelayEndReason.index_of(reason) + 1, flag))
3800    stem.response.convert('SINGLELINE', response)
3801
3802    if not response.is_ok():
3803      if response.code in ('512', '552'):
3804        if response.message.startswith('Unknown stream '):
3805          raise stem.InvalidArguments(response.code, response.message, [stream_id])
3806        elif response.message.startswith('Unrecognized reason '):
3807          raise stem.InvalidArguments(response.code, response.message, [reason])
3808        raise stem.InvalidRequest(response.code, response.message)
3809      else:
3810        raise stem.ProtocolError('CLOSESTREAM returned unexpected response code: %s' % response.code)
3811
3812  def signal(self, signal):
3813    """
3814    Sends a signal to the Tor client.
3815
3816    :param stem.Signal signal: type of signal to be sent
3817
3818    :raises:
3819      * :class:`stem.ControllerError` if sending the signal failed
3820      * :class:`stem.InvalidArguments` if signal provided wasn't recognized
3821    """
3822
3823    response = self.msg('SIGNAL %s' % signal)
3824    stem.response.convert('SINGLELINE', response)
3825
3826    if response.is_ok():
3827      if signal == stem.Signal.NEWNYM:
3828        self._last_newnym = time.time()
3829    else:
3830      if response.code == '552':
3831        raise stem.InvalidArguments(response.code, response.message, [signal])
3832
3833      raise stem.ProtocolError('SIGNAL response contained unrecognized status code: %s' % response.code)
3834
3835  def is_newnym_available(self):
3836    """
3837    Indicates if tor would currently accept a NEWNYM signal. This can only
3838    account for signals sent via this controller.
3839
3840    .. versionadded:: 1.2.0
3841
3842    :returns: **True** if tor would currently accept a NEWNYM signal, **False**
3843      otherwise
3844    """
3845
3846    if self.is_alive():
3847      return self.get_newnym_wait() == 0.0
3848    else:
3849      return False
3850
3851  def get_newnym_wait(self):
3852    """
3853    Provides the number of seconds until a NEWNYM signal would be respected.
3854    This can only account for signals sent via this controller.
3855
3856    .. versionadded:: 1.2.0
3857
3858    :returns: **float** for the number of seconds until tor would respect
3859      another NEWNYM signal
3860    """
3861
3862    return max(0.0, self._last_newnym + 10 - time.time())
3863
3864  @with_default()
3865  def get_effective_rate(self, default = UNDEFINED, burst = False):
3866    """
3867    get_effective_rate(default = UNDEFINED, burst = False)
3868
3869    Provides the maximum rate this relay is configured to relay in bytes per
3870    second. This is based on multiple torrc parameters if they're set...
3871
3872    * Effective Rate = min(BandwidthRate, RelayBandwidthRate, MaxAdvertisedBandwidth)
3873    * Effective Burst = min(BandwidthBurst, RelayBandwidthBurst)
3874
3875    .. versionadded:: 1.3.0
3876
3877    :param object default: response if the query fails
3878    :param bool burst: provides the burst bandwidth, otherwise this provides
3879      the standard rate
3880
3881    :returns: **int** with the effective bandwidth rate in bytes per second
3882
3883    :raises: :class:`stem.ControllerError` if the call fails and no default was
3884      provided
3885    """
3886
3887    if not burst:
3888      attributes = ('BandwidthRate', 'RelayBandwidthRate', 'MaxAdvertisedBandwidth')
3889    else:
3890      attributes = ('BandwidthBurst', 'RelayBandwidthBurst')
3891
3892    value = None
3893
3894    for attr in attributes:
3895      attr_value = int(self.get_conf(attr))
3896
3897      if attr_value == 0 and attr.startswith('Relay'):
3898        continue  # RelayBandwidthRate and RelayBandwidthBurst default to zero
3899
3900      value = min(value, attr_value) if value else attr_value
3901
3902    return value
3903
3904  def is_geoip_unavailable(self):
3905    """
3906    Provides **True** if tor's geoip database is unavailable, **False**
3907    otherwise.
3908
3909    .. versionchanged:: 1.6.0
3910       No longer requires previously failed GETINFO requests to determine this.
3911
3912    .. deprecated:: 1.6.0
3913       This is available as of Tor 0.3.2.1 through the following instead...
3914
3915       ::
3916
3917         controller.get_info('ip-to-country/ipv4-available', 0) == '1'
3918
3919    :returns: **bool** indicating if we've determined tor's geoip database to
3920      be unavailable or not
3921    """
3922
3923    if self._is_geoip_unavailable is None:
3924      try:
3925        self.get_info('ip-to-country/0.0.0.0')
3926        self._is_geoip_unavailable = False
3927      except stem.ControllerError as exc:
3928        if 'GeoIP data not loaded' in str(exc):
3929          self._is_geoip_unavailable = True
3930        else:
3931          return False  # unexpected issue, fail open and don't cache
3932
3933    return self._is_geoip_unavailable
3934
3935  def map_address(self, mapping):
3936    """
3937    Map addresses to replacement addresses. Tor replaces subseqent connections
3938    to the original addresses with the replacement addresses.
3939
3940    If the original address is a null address, i.e., one of '0.0.0.0', '::0', or
3941    '.' Tor picks an original address itself and returns it in the reply. If the
3942    original address is already mapped to a different address the mapping is
3943    removed.
3944
3945    :param dict mapping: mapping of original addresses to replacement addresses
3946
3947    :raises:
3948      * :class:`stem.InvalidRequest` if the addresses are malformed
3949      * :class:`stem.OperationFailed` if Tor couldn't fulfill the request
3950
3951    :returns: **dict** with 'original -> replacement' address mappings
3952    """
3953
3954    mapaddress_arg = ' '.join(['%s=%s' % (k, v) for (k, v) in list(mapping.items())])
3955    response = self.msg('MAPADDRESS %s' % mapaddress_arg)
3956    stem.response.convert('MAPADDRESS', response)
3957
3958    return response.entries
3959
3960  def drop_guards(self):
3961    """
3962    Drops our present guard nodes and picks a new set.
3963
3964    .. versionadded:: 1.2.0
3965
3966    :raises: :class:`stem.ControllerError` if Tor couldn't fulfill the request
3967    """
3968
3969    if self.get_version() < stem.version.Requirement.DROPGUARDS:
3970      raise stem.UnsatisfiableRequest(message = 'DROPGUARDS was added in tor version %s' % stem.version.Requirement.DROPGUARDS)
3971
3972    self.msg('DROPGUARDS')
3973
3974  def _post_authentication(self):
3975    super(Controller, self)._post_authentication()
3976
3977    # try to re-attach event listeners to the new instance
3978
3979    with self._event_listeners_lock:
3980      try:
3981        failed_events = self._attach_listeners()[1]
3982
3983        if failed_events:
3984          # remove our listeners for these so we don't keep failing
3985          for event_type in failed_events:
3986            del self._event_listeners[event_type]
3987
3988          logging_id = 'stem.controller.event_reattach-%s' % '-'.join(failed_events)
3989          log.log_once(logging_id, log.WARN, 'We were unable to re-attach our event listeners to the new tor instance for: %s' % ', '.join(failed_events))
3990      except stem.ProtocolError as exc:
3991        log.warn('Unable to issue the SETEVENTS request to re-attach our listeners (%s)' % exc)
3992
3993    # issue TAKEOWNERSHIP if we're the owning process for this tor instance
3994
3995    owning_pid = self.get_conf('__OwningControllerProcess', None)
3996
3997    if owning_pid == str(os.getpid()) and self.is_localhost():
3998      response = self.msg('TAKEOWNERSHIP')
3999      stem.response.convert('SINGLELINE', response)
4000
4001      if response.is_ok():
4002        # Now that tor is tracking our ownership of the process via the control
4003        # connection, we can stop having it check for us via our pid.
4004
4005        try:
4006          self.reset_conf('__OwningControllerProcess')
4007        except stem.ControllerError as exc:
4008          log.warn("We were unable to reset tor's __OwningControllerProcess configuration. It will continue to periodically check if our pid exists. (%s)" % exc)
4009      else:
4010        log.warn('We were unable assert ownership of tor through TAKEOWNERSHIP, despite being configured to be the owning process through __OwningControllerProcess. (%s)' % response)
4011
4012  def _handle_event(self, event_message):
4013    try:
4014      stem.response.convert('EVENT', event_message)
4015      event_type = event_message.type
4016    except stem.ProtocolError as exc:
4017      log.error('Tor sent a malformed event (%s): %s' % (exc, event_message))
4018      event_type = MALFORMED_EVENTS
4019
4020    with self._event_listeners_lock:
4021      for listener_type, event_listeners in list(self._event_listeners.items()):
4022        if listener_type == event_type:
4023          for listener in event_listeners:
4024            try:
4025              listener(event_message)
4026            except Exception as exc:
4027              log.warn('Event listener raised an uncaught exception (%s): %s' % (exc, event_message))
4028
4029  def _attach_listeners(self):
4030    """
4031    Attempts to subscribe to the self._event_listeners events from tor. This is
4032    a no-op if we're not currently authenticated.
4033
4034    :returns: tuple of the form (set_events, failed_events)
4035
4036    :raises: :class:`stem.ControllerError` if unable to make our request to tor
4037    """
4038
4039    set_events, failed_events = [], []
4040
4041    with self._event_listeners_lock:
4042      if self.is_authenticated():
4043        # try to set them all
4044        response = self.msg('SETEVENTS %s' % ' '.join(self._event_listeners.keys()))
4045
4046        if response.is_ok():
4047          set_events = list(self._event_listeners.keys())
4048        else:
4049          # One of the following likely happened...
4050          #
4051          # * Our user attached listeners before having an authenticated
4052          #   connection, so we couldn't check if we met the version
4053          #   requirement.
4054          #
4055          # * User attached listeners to one tor instance, then connected us to
4056          #   an older tor instancce.
4057          #
4058          # * Some other controller hiccup (far less likely).
4059          #
4060          # See if we can set some subset of our events.
4061
4062          for event in list(self._event_listeners.keys()):
4063            response = self.msg('SETEVENTS %s' % ' '.join(set_events + [event]))
4064
4065            if response.is_ok():
4066              set_events.append(event)
4067            else:
4068              failed_events.append(event)
4069
4070    return (set_events, failed_events)
4071
4072
4073def _parse_circ_path(path):
4074  """
4075  Parses a circuit path as a list of **(fingerprint, nickname)** tuples. Tor
4076  circuit paths are defined as being of the form...
4077
4078  ::
4079
4080    Path = LongName *("," LongName)
4081    LongName = Fingerprint [ ( "=" / "~" ) Nickname ]
4082
4083    example:
4084    $999A226EBED397F331B612FE1E4CFAE5C1F201BA=piyaz
4085
4086  ... *unless* this is prior to tor version 0.2.2.1 with the VERBOSE_NAMES
4087  feature turned off (or before version 0.1.2.2 where the feature was
4088  introduced). In that case either the fingerprint or nickname in the tuple
4089  will be **None**, depending on which is missing.
4090
4091  ::
4092
4093    Path = ServerID *("," ServerID)
4094    ServerID = Nickname / Fingerprint
4095
4096    example:
4097    $E57A476CD4DFBD99B4EE52A100A58610AD6E80B9,hamburgerphone,PrivacyRepublic14
4098
4099  :param str path: circuit path to be parsed
4100
4101  :returns: list of **(fingerprint, nickname)** tuples, fingerprints do not have a proceeding '$'
4102
4103  :raises: :class:`stem.ProtocolError` if the path is malformed
4104  """
4105
4106  if path:
4107    try:
4108      return [_parse_circ_entry(entry) for entry in path.split(',')]
4109    except stem.ProtocolError as exc:
4110      # include the path with the exception
4111      raise stem.ProtocolError('%s: %s' % (exc, path))
4112  else:
4113    return []
4114
4115
4116def _parse_circ_entry(entry):
4117  """
4118  Parses a single relay's 'LongName' or 'ServerID'. See the
4119  :func:`~stem.control._parse_circ_path` function for more information.
4120
4121  :param str entry: relay information to be parsed
4122
4123  :returns: **(fingerprint, nickname)** tuple
4124
4125  :raises: :class:`stem.ProtocolError` if the entry is malformed
4126  """
4127
4128  if '=' in entry:
4129    # common case
4130    fingerprint, nickname = entry.split('=')
4131  elif '~' in entry:
4132    # this is allowed for by the spec, but I've never seen it used
4133    fingerprint, nickname = entry.split('~')
4134  elif entry[0] == '$':
4135    # old style, fingerprint only
4136    fingerprint, nickname = entry, None
4137  else:
4138    # old style, nickname only
4139    fingerprint, nickname = None, entry
4140
4141  if fingerprint is not None:
4142    if not stem.util.tor_tools.is_valid_fingerprint(fingerprint, True):
4143      raise stem.ProtocolError('Fingerprint in the circuit path is malformed (%s)' % fingerprint)
4144
4145    fingerprint = fingerprint[1:]  # strip off the leading '$'
4146
4147  if nickname is not None and not stem.util.tor_tools.is_valid_nickname(nickname):
4148    raise stem.ProtocolError('Nickname in the circuit path is malformed (%s)' % nickname)
4149
4150  return (fingerprint, nickname)
4151
4152
4153@with_default()
4154def _case_insensitive_lookup(entries, key, default = UNDEFINED):
4155  """
4156  Makes a case insensitive lookup within a list or dictionary, providing the
4157  first matching entry that we come across.
4158
4159  :param list,dict entries: list or dictionary to be searched
4160  :param str key: entry or key value to look up
4161  :param object default: value to be returned if the key doesn't exist
4162
4163  :returns: case insensitive match or default if one was provided and key wasn't found
4164
4165  :raises: **ValueError** if no such value exists
4166  """
4167
4168  if entries is not None:
4169    if isinstance(entries, dict):
4170      for k, v in list(entries.items()):
4171        if k.lower() == key.lower():
4172          return v
4173    else:
4174      for entry in entries:
4175        if entry.lower() == key.lower():
4176          return entry
4177
4178  raise ValueError("key '%s' doesn't exist in dict: %s" % (key, entries))
4179
4180
4181def _get_with_timeout(event_queue, timeout, start_time):
4182  """
4183  Pulls an item from a queue with a given timeout.
4184  """
4185
4186  if timeout:
4187    time_left = timeout - (time.time() - start_time)
4188
4189    if time_left <= 0:
4190      raise stem.Timeout('Reached our %0.1f second timeout' % timeout)
4191
4192    try:
4193      return event_queue.get(True, time_left)
4194    except queue.Empty:
4195      raise stem.Timeout('Reached our %0.1f second timeout' % timeout)
4196  else:
4197    return event_queue.get()
4198