Stem Docs

Controller Responses

Controller Responses

Parses replies from the control socket.

Module Overview:

convert - translates a ControlMessage into a particular response subclass

ControlMessage - Message that's read from the control socket.
  |- SingleLineResponse - Simple tor response only including a single line of information.
  |
  |- from_str - provides a ControlMessage for the given string
  |- is_ok - response had a 250 status
  |- content - provides the parsed message content
  +- raw_content - unparsed socket data

ControlLine - String subclass with methods for parsing controller responses.
  |- remainder - provides the unparsed content
  |- is_empty - checks if the remaining content is empty
  |- is_next_quoted - checks if the next entry is a quoted value
  |- is_next_mapping - checks if the next entry is a KEY=VALUE mapping
  |- peek_key - provides the key of the next entry
  |- pop - removes and returns the next entry
  +- pop_mapping - removes and returns the next entry as a KEY=VALUE mapping
stem.response.convert(response_type, message, **kwargs)[source]

Converts a ControlMessage into a particular kind of tor response. This does an in-place conversion of the message from being a ControlMessage to a subclass for its response type. Recognized types include...

response_type Class
ADD_ONION stem.response.add_onion.AddOnionResponse
AUTHCHALLENGE stem.response.authchallenge.AuthChallengeResponse
EVENT stem.response.events.Event subclass
GETCONF stem.response.getconf.GetConfResponse
GETINFO stem.response.getinfo.GetInfoResponse
MAPADDRESS stem.response.mapaddress.MapAddressResponse
PROTOCOLINFO stem.response.protocolinfo.ProtocolInfoResponse
SINGLELINE stem.response.SingleLineResponse
Parameters:
  • response_type (str) -- type of tor response to convert to
  • message (stem.response.ControlMessage) -- message to be converted
  • kwargs -- optional keyword arguments to be passed to the parser method
Raises :
  • stem.ProtocolError the message isn't a proper response of that type
  • stem.InvalidArguments the arguments given as input are invalid, this is can only be raised if the response_type is: GETINFO, GETCONF
  • stem.InvalidRequest the arguments given as input are invalid, this is can only be raised if the response_type is: MAPADDRESS
  • stem.OperationFailed if the action the event represents failed, this is can only be raised if the response_type is: MAPADDRESS
  • TypeError if argument isn't a ControlMessage or response_type isn't supported
class stem.response.ControlMessage(parsed_content, raw_content, arrived_at=None)[source]

Bases: object

Message from the control socket. This is iterable and can be stringified for individual message components stripped of protocol formatting. Messages are never empty.

Variables:arrived_at (int) -- unix timestamp for when the message arrived

Changed in version 1.7.0: Implemented equality and hashing.

Changed in version 1.8.0: Moved arrived_at from the Event class up to this base ControlMessage.

static from_str(content, msg_type=None, normalize=False, **kwargs)[source]

Provides a ControlMessage for the given content.

New in version 1.1.0.

Changed in version 1.6.0: Added the normalize argument.

Parameters:
  • content (str) -- message to construct the message from
  • msg_type (str) -- type of tor reply to parse the content as
  • normalize (bool) -- ensures expected carriage return and ending newline are present
  • kwargs -- optional keyword arguments to be passed to the parser method
Returns:

stem.response.ControlMessage instance

is_ok()[source]

Checks if any of our lines have a 250 response.

Returns:True if any lines have a 250 response code, False otherwise
content(get_bytes=False)[source]

Provides the parsed message content. These are entries of the form...

(status_code, divider, content)
status_code
Three character code for the type of response (defined in section 4 of the control-spec).
divider
Single character to indicate if this is mid-reply, data, or an end to the message (defined in section 2.3 of the control-spec).
content
The following content is the actual payload of the line.

For data entries the content is the full multi-line payload with newline linebreaks and leading periods unescaped.

The status_code and divider are both strings (bytes in python 2.x and unicode in python 3.x). The content however is bytes if get_bytes is True.

Changed in version 1.1.0: Added the get_bytes argument.

Parameters:get_bytes (bool) -- provides bytes for the content rather than a str
Returns:list of (str, str, str) tuples for the components of this message
raw_content(get_bytes=False)[source]

Provides the unparsed content read from the control socket.

Changed in version 1.1.0: Added the get_bytes argument.

Parameters:get_bytes (bool) -- if True then this provides bytes rather than a str
Returns:str of the socket data used to generate this message
class stem.response.ControlLine(value)[source]

Bases: str

String subclass that represents a line of controller output. This behaves as a normal string with additional methods for parsing and popping entries from a space delimited series of elements like a stack.

None of these additional methods effect ourselves as a string (which is still immutable). All methods are thread safe.

remainder()[source]

Provides our unparsed content. This is an empty string after we've popped all entries.

Returns:str of the unparsed content
is_empty()[source]

Checks if we have further content to pop or not.

Returns:True if we have additional content, False otherwise
is_next_quoted(escaped=False)[source]

Checks if our next entry is a quoted value or not.

Parameters:escaped (bool) -- unescapes the string
Returns:True if the next entry can be parsed as a quoted value, False otherwise
is_next_mapping(key=None, quoted=False, escaped=False)[source]

Checks if our next entry is a KEY=VALUE mapping or not.

Parameters:
  • key (str) -- checks that the key matches this value, skipping the check if None
  • quoted (bool) -- checks that the mapping is to a quoted value
  • escaped (bool) -- unescapes the string
Returns:

True if the next entry can be parsed as a key=value mapping, False otherwise

peek_key()[source]

Provides the key of the next entry, providing None if it isn't a key/value mapping.

Returns:str with the next entry's key
pop(quoted=False, escaped=False)[source]

Parses the next space separated entry, removing it and the space from our remaining content. Examples...

>>> line = ControlLine("\"We're all mad here.\" says the grinning cat.")
>>> print line.pop(True)
  "We're all mad here."
>>> print line.pop()
  "says"
>>> print line.remainder()
  "the grinning cat."

>>> line = ControlLine("\"this has a \\\" and \\\\ in it\" foo=bar more_data")
>>> print line.pop(True, True)
  "this has a \" and \\ in it"
Parameters:
  • quoted (bool) -- parses the next entry as a quoted value, removing the quotes
  • escaped (bool) -- unescapes the string
Returns:

str of the next space separated entry

Raises :
  • ValueError if quoted is True without the value being quoted
  • IndexError if we don't have any remaining content left to parse
pop_mapping(quoted=False, escaped=False, get_bytes=False)[source]

Parses the next space separated entry as a KEY=VALUE mapping, removing it and the space from our remaining content.

Changed in version 1.6.0: Added the get_bytes argument.

Parameters:
  • quoted (bool) -- parses the value as being quoted, removing the quotes
  • escaped (bool) -- unescapes the string
  • get_bytes (bool) -- provides bytes for the value rather than a str
Returns:

tuple of the form (key, value)

Raises :

ValueError if this isn't a KEY=VALUE mapping or if quoted is True without the value being quoted

Raises :

IndexError if there's nothing to parse from the line

class stem.response.SingleLineResponse(parsed_content, raw_content, arrived_at=None)[source]

Bases: stem.response.ControlMessage

Reply to a request that performs an action rather than querying data. These requests only contain a single line, which is 'OK' if successful, and a description of the problem if not.

Variables:
  • code (str) -- status code for our line
  • message (str) -- content of the line
is_ok(strict=False)[source]

Checks if the response code is "250". If strict is True then this checks if the response is "250 OK"

Parameters:strict (bool) -- checks for a "250 OK" message if True
Returns:
  • If strict is False: True if the response code is "250", False otherwise
  • If strict is True: True if the response is "250 OK", False otherwise

Responses

class stem.response.add_onion.AddOnionResponse(parsed_content, raw_content, arrived_at=None)[source]

Bases: stem.response.ControlMessage

ADD_ONION response.

Variables:
  • service_id (str) -- hidden service address without the '.onion' suffix
  • private_key (str) -- base64 encoded hidden service private key
  • private_key_type (str) -- crypto used to generate the hidden service private key (such as RSA1024)
  • client_auth (dict) -- newly generated client credentials the service accepts
class stem.response.authchallenge.AuthChallengeResponse(parsed_content, raw_content, arrived_at=None)[source]

Bases: stem.response.ControlMessage

AUTHCHALLENGE query response.

Variables:
  • server_hash (str) -- server hash provided by tor
  • server_nonce (str) -- server nonce provided by tor
class stem.response.getconf.GetConfResponse(parsed_content, raw_content, arrived_at=None)[source]

Bases: stem.response.ControlMessage

Reply for a GETCONF query.

Note that configuration parameters won't match what we queried for if it's one of the special mapping options (ex. 'HiddenServiceOptions').

Variables:entries (dict) -- mapping between the config parameter (str) and their values (list of str)
class stem.response.getinfo.GetInfoResponse(parsed_content, raw_content, arrived_at=None)[source]

Bases: stem.response.ControlMessage

Reply for a GETINFO query.

Variables:entries (dict) -- mapping between the queried options and their bytes values
class stem.response.mapaddress.MapAddressResponse(parsed_content, raw_content, arrived_at=None)[source]

Bases: stem.response.ControlMessage

Reply for a MAPADDRESS query. Doesn't raise an exception unless no addresses were mapped successfully.

Variables:

entries (dict) -- mapping between the original and replacement addresses

Raises :

Events