Low-Level Protocol Classes

build_tor_connection

txtorcon.build_tor_connection(connection, build_state=True, wait_for_proto=True, password_function=<function <lambda>>)

This is used to build a valid TorState (which has .protocol for the TorControlProtocol). For example:

from twisted.internet import reactor
from twisted.internet.endpoints import TCP4ClientEndpoint
import txtorcon

def example(state):
    print "Fully bootstrapped state:",state
    print "   with bootstrapped protocol:",state.protocol

d = txtorcon.build_tor_connection(TCP4ClientEndpoint(reactor,
                                                     "localhost",
                                                     9051))
d.addCallback(example)
reactor.run()
Parameters:
  • password_function – See txtorcon.TorControlProtocol
  • build_state – If True (the default) a TorState object will be built as well. If False, just a TorControlProtocol will be returned via the Deferred.
Returns:

a Deferred that fires with a TorControlProtocol or, if you specified build_state=True, a TorState. In both cases, the object has finished bootstrapping (i.e. TorControlProtocol.post_bootstrap or TorState.post_bootstap has fired, as needed)

build_local_tor_connection

txtorcon.build_local_tor_connection(reactor, host='127.0.0.1', port=9051, socket='/var/run/tor/control', *args, **kwargs)

This builds a connection to a local Tor, either via 127.0.0.1:9051 (which is tried first) or /var/run/tor/control (by default). See also build_tor_connection for other key-word arguments that are accepted here also.

Parameters:
  • host – An IP address to find Tor at. Corresponds to the ControlListenAddress torrc option.
  • port – The port to use with the address when trying to contact Tor. This corresponds to the ControlPort option in torrc (default is 9051).

TorControlProtocol

class txtorcon.TorControlProtocol(password_function=None)

Bases: twisted.protocols.basic.LineOnlyReceiver

This is the main class that talks to a Tor and implements the “raw” procotol.

This instance does not track state; see txtorcon.TorState for the current state of all Circuits, Streams and Routers.

txtorcon.TorState.build_circuit() allows you to build custom circuits.

txtorcon.TorControlProtocol.add_event_listener() can be used to listen for specific events.

To see how circuit and stream listeners are used, see txtorcon.TorState, which is also the place to go if you wish to add your own stream or circuit listeners.

Parameters:password_function – A zero-argument callable which returns a password (or Deferred). It is only called if the Tor doesn’t have COOKIE authentication turned on. Tor’s default is COOKIE.
password_function = None

If set, a callable to query for a password to use for authentication to Tor (default is to use COOKIE, however). May return Deferred.

version = None

Version of Tor we’ve connected to.

is_owned = None

If not None, this is the PID of the Tor process we own (TAKEOWNERSHIP, etc).

events = None

events we’ve subscribed to (keyed by name like “GUARD”, “STREAM”)

valid_events = None

all valid events (name -> Event instance)

valid_signals = None

A list of all valid signals we accept from Tor

on_disconnect = None

This Deferred is triggered when the connection is closed. If there was an error, the errback is called instead.

post_bootstrap = None

This Deferred is triggered when we’re done setting up (authentication, getting information from Tor). You will want to use this to do things with the TorControlProtocol class when it’s set up, like:

def setup_complete(proto):
    print "Setup complete, attached to Tor version",proto.version

def setup(proto):
    proto.post_bootstrap.addCallback(setup_complete)

ep = TCP4ClientEndpoint(reactor, "localhost", 9051)
ep.connect(TorProtocolFactory())
d.addCallback(setup)

See the helper method txtorcon.build_tor_connection().

start_debug()
stop_debug()
graphviz_data()
get_info_raw(*args)

Mostly for internal use; gives you the raw string back from the GETINFO command. See getinfo

get_info_incremental(key, line_cb)

Mostly for internal use; calls GETINFO for a single key and calls line_cb with each line received, as it is received.

See getinfo

get_info(*args)

Uses GETINFO to obtain informatoin from Tor.

Parameters:args

should be a list or tuple of strings which are valid information keys. For valid keys, see control-spec.txt from torspec.

Todo

make some way to automagically obtain valid keys, either from running Tor or parsing control-spec

Returns:a Deferred which will callback with a dict containing the keys you asked for. If you want to avoid the parsing into a dict, you can use get_info_raw instead.
get_conf(*args)

Uses GETCONF to obtain configuration values from Tor.

Parameters:args – any number of strings which are keys to get. To get all valid configuraiton names, you can call: get_info('config/names')
Returns:a Deferred which callbacks with one or many configuration values (depends on what you asked for). See control-spec for valid keys (you can also use TorConfig which will come set up with all the keys that are valid). The value will be a dict.

Note that Tor differentiates between an empty value and a default value; in the raw protocol one looks like ‘250 MyFamily’ versus ‘250 MyFamily=’ where the latter is set to the empty string and the former is a default value. We differentiate these by setting the value in the dict to DEFAULT_VALUE for the default value case, or an empty string otherwise.

get_conf_raw(*args)

Same as get_conf, except that the results are not parsed into a dict

set_conf(*args)

set configuration values. see control-spec for valid keys. args is treated as a list containing name then value pairs. For example, set_conf('foo', 'bar') will (attempt to) set the key ‘foo’ to value ‘bar’.

Returns:a Deferred that will callback with the response (‘OK’) or errback with the error code and message (e.g. "552 Unrecognized option: Unknown option 'foo'.  Failing.")
signal(nm)

Issues a signal to Tor. See control-spec or txtorcon.TorControlProtocol.valid_signals for which ones are available and their return values.

Returns:a Deferred which callbacks with Tor’s response (OK or something like 552 Unrecognized signal code "foo").
add_event_listener(evt, callback)

Add a listener to an Event object. This may be called multiple times for the same event. If it’s the first listener, a new SETEVENTS call will be initiated to Tor.

Parameters:
  • evt – event name, see also txtorcon.TorControlProtocol.events .keys(). These event names are queried from Tor (with GETINFO events/names)
  • callback – any callable that takes a single argument which receives the text collected for the event from the tor control protocol.

For more information on the events supported, see control-spec section 4.1

Note

this is a low-level interface; if you want to follow circuit or stream creation etc. see TorState and methods like add_circuit_listener

Return:None

Todo

  • should have an interface for the callback
  • show how to tie in Stem parsing if you want
remove_event_listener(evt, cb)

The opposite of TorControlProtocol.add_event_listener()

Parameters:
  • evt – the event name (or an Event object)
  • cb – the callback object to remove
protocolinfo()
Returns:a Deferred which will give you PROTOCOLINFO; see control-spec
authenticate(passphrase)

Call the AUTHENTICATE command.

Quoting torspec/control-spec.txt: “The authentication token can be specified as either a quoted ASCII string, or as an unquoted hexadecimal encoding of that same string (to avoid escaping issues).”

quit()

Sends the QUIT command, which asks Tor to hang up on this controller connection.

If you’ve taken ownership of the Tor to which you’re connected, this should also cause it to exit. Otherwise, it won’t.

queue_command(cmd, arg=None)

returns a Deferred which will fire with the response data when we get it

Note that basically every request is ultimately funelled through this command.

lineReceived(line)

twisted.protocols.basic.LineOnlyReceiver API

connectionMade()

Protocol API

connectionLost(reason)

Protocol API

TorProtocolFactory

class txtorcon.TorProtocolFactory(password_function=<function <lambda>>)

Bases: object

Builds TorControlProtocol objects. Implements IProtocolFactory for Twisted interaction.

If your running Tor doesn’t support COOKIE authentication, then you should supply a password callback.

Builds protocols to talk to a Tor client on the specified address. For example:

ep = TCP4ClientEndpoint(reactor, "localhost", 9051)
ep.connect(TorProtocolFactory())
reactor.run()

By default, COOKIE authentication is used if available.

Parameters:password_function – If supplied, this is a zero-argument method that returns a password (or a Deferred). By default, it returns None. This is only queried if the Tor we connect to doesn’t support (or hasn’t enabled) COOKIE authentication.
doStart()

twisted.internet.interfaces.IProtocolFactory API

doStop()

twisted.internet.interfaces.IProtocolFactory API

buildProtocol(addr)

twisted.internet.interfaces.IProtocolFactory API

TorProcessProtocol

class txtorcon.TorProcessProtocol(connection_creator, progress_updates=None, config=None, ireactortime=None, timeout=None, kill_on_stderr=True, stdout=None, stderr=None)

Bases: twisted.internet.protocol.ProcessProtocol

This will read the output from a Tor process and attempt a connection to its control port when it sees any ‘Bootstrapped’ message on stdout. You probably don’t need to use this directly except as the return value from the txtorcon.launch_tor() method. tor_protocol contains a valid txtorcon.TorControlProtocol instance by that point.

connection_creator is a callable that should return a Deferred that callbacks with a txtorcon.TorControlProtocol; see txtorcon.launch_tor() for the default one which is a functools.partial that will call connect(TorProtocolFactory()) on an appropriate twisted.internet.endpoints.TCP4ClientEndpoint

Parameters:
  • connection_creator – A no-parameter callable which returns a Deferred which promises a IStreamClientEndpoint. If this is None, we do NOT attempt to connect to the underlying Tor process.
  • progress_updates – A callback which received progress updates with three args: percent, tag, summary
  • config – a TorConfig object to connect to the TorControlProtocl from the launched tor (should it succeed)
  • ireactortime – An object implementing IReactorTime (i.e. a reactor) which needs to be supplied if you pass a timeout.
  • timeout – An int representing the timeout in seconds. If we are unable to reach 100% by this time we will consider the setting up of Tor to have failed. Must supply ireactortime if you supply this.
  • kill_on_stderr – When True, kill subprocess if we receive anything on stderr
  • stdout – Anything subprocess writes to stdout is sent to .write() on this
  • stderr – Anything subprocess writes to stderr is sent to .write() on this
Variables:

tor_protocol – The TorControlProtocol instance connected to the Tor this ProcessProtocol>` is speaking to. Will be valid after the Deferred returned from TorProcessProtocol.when_connected() is triggered.

when_connected()
quit()

This will terminate (with SIGTERM) the underlying Tor process.

Returns:a Deferred that callback()’s (with None) when the process has actually exited.
outReceived(data)

ProcessProtocol API

errReceived(data)

ProcessProtocol API

cleanup()

Clean up my temporary files.

processExited(reason)
processEnded(status)

ProcessProtocol API

progress(percent, tag, summary)

Can be overridden or monkey-patched if you want to get progress updates yourself.