[stem/master] Revised API docs for stem.connection

commit ec185b901de8829f12c7e0c1778f079e444ce14a Author: Damian Johnson <atagar@torproject.org> Date: Sat Oct 27 17:26:35 2012 -0700 Revised API docs for stem.connection --- docs/api.rst | 14 ++- docs/api/connection.rst | 5 + docs/contents.rst | 8 +- stem/connection.py | 252 ++++++++++++++++++++++++++++------------------ 4 files changed, 173 insertions(+), 106 deletions(-) diff --git a/docs/api.rst b/docs/api.rst index e35a29a..65fa524 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -1,11 +1,17 @@ API === -Types ------ +Controller +---------- -* `stem.exit_policy <api/exit_policy.html>`_ - Relay policy for the destinations it will or won't allow traffic to. -* `stem.version <api/version.html>`_ - Tor versions that can be compared to determine Tor's capablilites. +* **Core** + + * `stem.connection <api/connection.html>`_ - Connection and authentication to the Tor control port or socket. + +* **Types** + + * `stem.exit_policy <api/exit_policy.html>`_ - Relay policy for the destinations it will or won't allow traffic to. + * `stem.version <api/version.html>`_ - Tor versions that can be compared to determine Tor's capablilites. Descriptors ----------- diff --git a/docs/api/connection.rst b/docs/api/connection.rst new file mode 100644 index 0000000..115ba26 --- /dev/null +++ b/docs/api/connection.rst @@ -0,0 +1,5 @@ +Connection +========== + +.. automodule:: stem.connection + diff --git a/docs/contents.rst b/docs/contents.rst index 1be4021..467a122 100644 --- a/docs/contents.rst +++ b/docs/contents.rst @@ -8,18 +8,20 @@ Contents download tutorial + api/connection + api/exit_policy api/version - api/descriptor/export - api/descriptor/reader - api/descriptor/descriptor api/descriptor/server_descriptor api/descriptor/extrainfo_descriptor api/descriptor/networkstatus api/descriptor/router_status_entry + api/descriptor/export + api/descriptor/reader + api/util/conf api/util/connection api/util/enum diff --git a/stem/connection.py b/stem/connection.py index 6f32972..85b318a 100644 --- a/stem/connection.py +++ b/stem/connection.py @@ -1,14 +1,15 @@ """ -Functions for connecting and authenticating to the tor process. Most commonly -you'll either want the 'connect_*' or 'authenticate' function. +Functions for connecting and authenticating to the tor process. -The 'connect_*' functions give an easy, one line method for getting an -authenticated control connection. This is handy for CLI applications and the -python interactive interpretor, but does several things that makes it -undesirable for applications (uses stdin/stdout, suppresses exceptions, etc). +The :func:`~stem.connection.connect_port` and +:func:`~stem.connection.connect_socket_file` functions give an easy, one line +method for getting an authenticated control connection. This is handy for CLI +applications and the python interactive interpretor, but does several things +that makes it undesirable for applications (uses stdin/stdout, suppresses +exceptions, etc). -The 'authenticate' function, however, gives easy but fine-grained control over -the authentication process. For instance... +The :func:`~stem.connection.authenticate` function, however, gives easy but +fine-grained control over the authentication process. For instance... :: @@ -108,13 +109,14 @@ def connect_port(control_addr = "127.0.0.1", control_port = 9051, password = Non Convenience function for quickly getting a control connection. This is very handy for debugging or CLI setup, handling setup and prompting for a password if necessary (and none is provided). If any issues arise this prints a - description of the problem and returns None. + description of the problem and returns **None**. :param str control_addr: ip address of the controller :param int control_port: port number of the controller :param str password: passphrase to authenticate to the socket :param str chroot_path: path prefix if in a chroot environment - :param Class controller: BaseController subclass to be returned, this provides a ControlSocket if None + :param Class controller: :class:`~stem.control.BaseController` subclass to be + returned, this provides a :class:`~stem.socket.ControlSocket` if **None** :returns: authenticated control connection, the type based on the controller argument """ @@ -130,12 +132,13 @@ def connect_port(control_addr = "127.0.0.1", control_port = 9051, password = Non def connect_socket_file(socket_path = "/var/run/tor/control", password = None, chroot_path = None, controller = stem.control.Controller): """ Convenience function for quickly getting a control connection. For more - information see the connect_port function. + information see the :func:`~stem.connection.connect_port` function. :param str socket_path: path where the control socket is located :param str password: passphrase to authenticate to the socket :param str chroot_path: path prefix if in a chroot environment - :param Class controller: BaseController subclass to be returned, this provides a ControlSocket if None + :param Class controller: :class:`~stem.control.BaseController` subclass to be + returned, this provides a :class:`~stem.socket.ControlSocket` if **None** :returns: authenticated control connection, the type based on the controller argument """ @@ -155,7 +158,8 @@ def _connect(control_socket, password, chroot_path, controller): :param stem.socket.ControlSocket control_socket: socket being authenticated to :param str password: passphrase to authenticate to the socket :param str chroot_path: path prefix if in a chroot environment - :param Class controller: BaseController subclass to be returned, this provides a ControlSocket if None + :param Class controller: :class:`~stem.control.BaseController` subclass to be + returned, this provides a :class:`~stem.socket.ControlSocket` if **None** :returns: authenticated control connection, the type based on the controller argument """ @@ -187,87 +191,93 @@ def authenticate(controller, password = None, chroot_path = None, protocolinfo_r All exceptions are subclasses of AuthenticationFailure so, in practice, callers should catch the types of authentication failure that they care - about, then have a AuthenticationFailure catch-all at the end. + about, then have a :class:`~stem.connection.AuthenticationFailure` catch-all + at the end. - This can authenticate to either a :class:`stem.control.BaseController` or - :class:`stem.socket.ControlSocket`. + This can authenticate to either a :class:`~stem.control.BaseController` or + :class:`~stem.socket.ControlSocket`. :param controller: tor controller or socket to be authenticated - :param str password: passphrase to present to the socket if it uses password authentication (skips password auth if None) + :param str password: passphrase to present to the socket if it uses password + authentication (skips password auth if **None**) :param str chroot_path: path prefix if in a chroot environment - :param stem.response.protocolinfo.ProtocolInfoResponse protocolinfo_response: tor protocolinfo response, this is retrieved on our own if None + :param stem.response.protocolinfo.ProtocolInfoResponse protocolinfo_response: + tor protocolinfo response, this is retrieved on our own if **None** - :raises: If all attempts to authenticate fails then this will raise a :class:`stem.connection.AuthenticationFailure` subclass. Since this may try multiple authentication methods it may encounter multiple exceptions. If so then the exception this raises is prioritized as follows... + :raises: If all attempts to authenticate fails then this will raise a + :class:`~stem.connection.AuthenticationFailure` subclass. Since this may + try multiple authentication methods it may encounter multiple exceptions. + If so then the exception this raises is prioritized as follows... - * :class:`stem.connection.IncorrectSocketType` + * :class:`~stem.connection.IncorrectSocketType` The controller does not speak the tor control protocol. Most often this happened because the user confused the SocksPort or ORPort with the ControlPort. - * :class:`stem.connection.UnrecognizedAuthMethods` + * :class:`~stem.connection.UnrecognizedAuthMethods` All of the authentication methods tor will accept are new and unrecognized. Please upgrade stem and, if that doesn't work, file a ticket on 'trac.torproject.org' and I'd be happy to add support. - * :class:`stem.connection.MissingPassword` + * :class:`~stem.connection.MissingPassword` We were unable to authenticate but didn't attempt password authentication because none was provided. You should prompt the user for a password and try again via 'authenticate_password'. - * :class:`stem.connection.IncorrectPassword` + * :class:`~stem.connection.IncorrectPassword` We were provided with a password but it was incorrect. - * :class:`stem.connection.IncorrectCookieSize` + * :class:`~stem.connection.IncorrectCookieSize` Tor allows for authentication by reading it a cookie file, but that file is the wrong size to be an authentication cookie. - * :class:`stem.connection.UnreadableCookieFile` + * :class:`~stem.connection.UnreadableCookieFile` Tor allows for authentication by reading it a cookie file, but we can't read that file (probably due to permissions). - * **\***:class:`stem.connection.IncorrectCookieValue` + * **\***:class:`~stem.connection.IncorrectCookieValue` Tor allows for authentication by reading it a cookie file, but rejected the contents of that file. - * **\***:class:`stem.connection.AuthChallengeUnsupported` + * **\***:class:`~stem.connection.AuthChallengeUnsupported` Tor doesn't recognize the AUTHCHALLENGE command. This is probably a Tor version prior to SAFECOOKIE being implement, but this exception shouldn't arise because we won't attempt SAFECOOKIE auth unless Tor claims to support it. - * **\***:class:`stem.connection.UnrecognizedAuthChallengeMethod` + * **\***:class:`~stem.connection.UnrecognizedAuthChallengeMethod` Tor couldn't recognize the AUTHCHALLENGE method Stem sent to it. This shouldn't happen at all. - * **\***:class:`stem.connection.InvalidClientNonce` + * **\***:class:`~stem.connection.InvalidClientNonce` Tor says that the client nonce provided by Stem during the AUTHCHALLENGE process is invalid. - * **\***:class:`stem.connection.AuthSecurityFailure` + * **\***:class:`~stem.connection.AuthSecurityFailure` Nonce value provided by the server was invalid. - * **\***:class:`stem.connection.OpenAuthRejected` + * **\***:class:`~stem.connection.OpenAuthRejected` Tor says that it allows for authentication without any credentials, but then rejected our authentication attempt. - * **\***:class:`stem.connection.MissingAuthInfo` + * **\***:class:`~stem.connection.MissingAuthInfo` Tor provided us with a PROTOCOLINFO reply that is technically valid, but missing the information we need to authenticate. - * **\***:class:`stem.connection.AuthenticationFailure` + * **\***:class:`~stem.connection.AuthenticationFailure` There are numerous other ways that authentication could have failed including socket failures, malformed controller responses, etc. These @@ -278,8 +288,8 @@ def authenticate(controller, password = None, chroot_path = None, protocolinfo_r to treat these as errors. If you have a use case where this commonly happens, please file a ticket on 'trac.torproject.org'. - In the future new :class:`stem.connection.AuthenticationFailure` subclasses - may be added to allow for better error handling. + In the future new :class:`~stem.connection.AuthenticationFailure` + subclasses may be added to allow for better error handling. """ if not protocolinfo_response: @@ -390,17 +400,20 @@ def authenticate_none(controller, suppress_ctl_errors = True): If authentication fails tor will disconnect and we'll make a best effort attempt to re-establish the connection. This may not succeed, so check - is_alive() before using the socket further. + :func:`~stem.socket.ControlSocket.is_alive` before using the socket further. - This can authenticate to either a :class:`stem.control.BaseController` or - :class:`stem.socket.ControlSocket`. + This can authenticate to either a :class:`~stem.control.BaseController` or + :class:`~stem.socket.ControlSocket`. - *For general usage use the authenticate() function instead.* + For general usage use the :func:`~stem.connection.authenticate` function + instead. :param controller: tor controller or socket to be authenticated - :param bool suppress_ctl_errors: reports raised :class:`stem.socket.ControllerError` as authentication rejection if True, otherwise they're re-raised + :param bool suppress_ctl_errors: reports raised + :class:`~stem.socket.ControllerError` as authentication rejection if + **True**, otherwise they're re-raised - :raises: :class:`stem.connection.OpenAuthRejected` if the empty authentication credentials aren't accepted + :raises: :class:`~stem.connection.OpenAuthRejected` if the empty authentication credentials aren't accepted """ try: @@ -426,25 +439,31 @@ def authenticate_password(controller, password, suppress_ctl_errors = True): If authentication fails tor will disconnect and we'll make a best effort attempt to re-establish the connection. This may not succeed, so check - is_alive() before using the socket further. + :func:`~stem.socket.ControlSocket.is_alive` before using the socket further. - If you use this function directly, rather than authenticate(), we may - mistakenly raise a PasswordAuthRejected rather than IncorrectPassword. This - is because we rely on tor's error messaging which is liable to change in - future versions (`ticket <https://trac.torproject.org/4817>`_). + If you use this function directly, rather than + :func:`~stem.connection.authenticate`, we may mistakenly raise a + PasswordAuthRejected rather than IncorrectPassword. This is because we rely + on tor's error messaging which is liable to change in future versions + (`ticket <https://trac.torproject.org/4817>`_). - This can authenticate to either a :class:`stem.control.BaseController` or - :class:`stem.socket.ControlSocket`. + This can authenticate to either a :class:`~stem.control.BaseController` or + :class:`~stem.socket.ControlSocket`. - *For general usage use the authenticate() function instead.* + For general usage use the :func:`~stem.connection.authenticate` function + instead. :param controller: tor controller or socket to be authenticated :param str password: passphrase to present to the socket - :param bool suppress_ctl_errors: reports raised :class:`stem.socket.ControllerError` as authentication rejection if True, otherwise they're re-raised + :param bool suppress_ctl_errors: reports raised + :class:`~stem.socket.ControllerError` as authentication rejection if + **True**, otherwise they're re-raised :raises: - * :class:`stem.connection.PasswordAuthRejected` if the socket doesn't accept password authentication - * :class:`stem.connection.IncorrectPassword` if the authentication credentials aren't accepted + * :class:`~stem.connection.PasswordAuthRejected` if the socket doesn't + accept password authentication + * :class:`~stem.connection.IncorrectPassword` if the authentication + credentials aren't accepted """ # Escapes quotes. Tor can include those in the password hash, in which case @@ -483,32 +502,42 @@ def authenticate_cookie(controller, cookie_path, suppress_ctl_errors = True): validation that this is a cookie before presenting the contents to the socket. - The IncorrectCookieSize and UnreadableCookieFile exceptions take precedence + The :class:`~stem.connection.IncorrectCookieSize` and + :class:`~stem.connection.UnreadableCookieFile` exceptions take precedence over the other types. If authentication fails tor will disconnect and we'll make a best effort attempt to re-establish the connection. This may not succeed, so check - is_alive() before using the socket further. + :func:`~stem.socket.ControlSocket.is_alive` before using the socket further. - If you use this function directly, rather than authenticate(), we may - mistakenly raise a CookieAuthRejected rather than IncorrectCookieValue. This - is because we rely on tor's error messaging which is liable to change in - future versions (`ticket <https://trac.torproject.org/4817>`_). + If you use this function directly, rather than + :func:`~stem.connection.authenticate`, we may mistakenly raise a + :class:`~stem.connection.CookieAuthRejected` rather than + :class:`~stem.connection.IncorrectCookieValue`. This is because we rely on + tor's error messaging which is liable to change in future versions (`ticket + <https://trac.torproject.org/4817>`_). - This can authenticate to either a :class:`stem.control.BaseController` or - :class:`stem.socket.ControlSocket`. + This can authenticate to either a :class:`~stem.control.BaseController` or + :class:`~stem.socket.ControlSocket`. - *For general usage use the authenticate() function instead.* + For general usage use the :func:`~stem.connection.authenticate` function + instead. :param controller: tor controller or socket to be authenticated :param str cookie_path: path of the authentication cookie to send to tor - :param bool suppress_ctl_errors: reports raised :class:`stem.socket.ControllerError` as authentication rejection if True, otherwise they're re-raised + :param bool suppress_ctl_errors: reports raised + :class:`~stem.socket.ControllerError` as authentication rejection if + **True**, otherwise they're re-raised :raises: - * :class:`stem.connection.IncorrectCookieSize` if the cookie file's size is wrong - * :class:`stem.connection.UnreadableCookieFile` if the cookie file doesn't exist or we're unable to read it - * :class:`stem.connection.CookieAuthRejected` if cookie authentication is attempted but the socket doesn't accept it - * :class:`stem.connection.IncorrectCookieValue` if the cookie file's value is rejected + * :class:`~stem.connection.IncorrectCookieSize` if the cookie file's size + is wrong + * :class:`~stem.connection.UnreadableCookieFile` if the cookie file doesn't + exist or we're unable to read it + * :class:`~stem.connection.CookieAuthRejected` if cookie authentication is + attempted but the socket doesn't accept it + * :class:`stem.connection.IncorrectCookieValue` if the cookie file's value + is rejected """ cookie_data = _read_cookie(cookie_path, False) @@ -551,36 +580,51 @@ def authenticate_safecookie(controller, cookie_path, suppress_ctl_errors = True) 2. generate a hash digest using the challenge received in the first step, and use it to authenticate the controller - The IncorrectCookieSize and UnreadableCookieFile exceptions take - precedence over the other exception types. + The :class:`~stem.connection.IncorrectCookieSize` and + :class:`~stem.connection.UnreadableCookieFile` exceptions take precedence + over the other exception types. - The AuthChallengeUnsupported, UnrecognizedAuthChallengeMethod, - InvalidClientNonce and CookieAuthRejected exceptions are next in the order of - precedence. Depending on the reason, one of these is raised if the first + The :class:`~stem.connection.AuthChallengeUnsupported`, + :class:`~stem.connection.UnrecognizedAuthChallengeMethod`, + :class:`~stem.connection.InvalidClientNonce` and + :class:`~stem.connection.CookieAuthRejected` exceptions are next in the order + of precedence. Depending on the reason, one of these is raised if the first (AUTHCHALLENGE) step fails. - In the second (AUTHENTICATE) step, IncorrectCookieValue or - CookieAuthRejected maybe raised. + In the second (AUTHENTICATE) step, + :class:`~stem.connection.IncorrectCookieValue` or + :class:`~stem.connection.CookieAuthRejected` maybe raised. If authentication fails tor will disconnect and we'll make a best effort attempt to re-establish the connection. This may not succeed, so check - is_alive() before using the socket further. + :func:`~stem.socket.ControlSocket.is_alive` before using the socket further. - For general usage use the authenticate() function instead. + For general usage use the :func:`~stem.connection.authenticate` function + instead. :param controller: tor controller or socket to be authenticated :param str cookie_path: path of the authentication cookie to send to tor - :param bool suppress_ctl_errors: reports raised :class:`stem.socket.ControllerError` as authentication rejection if True, otherwise they're re-raised + :param bool suppress_ctl_errors: reports raised + :class:`~stem.socket.ControllerError` as authentication rejection if + **True**, otherwise they're re-raised :raises: - * :class:`stem.connection.IncorrectCookieSize` if the cookie file's size is wrong - * :class:`stem.connection.UnreadableCookieFile` if the cookie file doesn't exist or we're unable to read it - * :class:`stem.connection.CookieAuthRejected` if cookie authentication is attempted but the socket doesn't accept it - * :class:`stem.connection.IncorrectCookieValue` if the cookie file's value is rejected - * :class:`stem.connection.UnrecognizedAuthChallengeMethod` if the Tor client fails to recognize the AuthChallenge method - * :class:`stem.connection.AuthChallengeUnsupported` if AUTHCHALLENGE is unimplemented, or if unable to parse AUTHCHALLENGE response - * :class:`stem.connection.AuthSecurityFailure` if AUTHCHALLENGE's response looks like a security attack - * :class:`stem.connection.InvalidClientNonce` if stem's AUTHCHALLENGE client nonce is rejected for being invalid + * :class:`~stem.connection.IncorrectCookieSize` if the cookie file's size + is wrong + * :class:`~stem.connection.UnreadableCookieFile` if the cookie file doesn't + exist or we're unable to read it + * :class:`~stem.connection.CookieAuthRejected` if cookie authentication is + attempted but the socket doesn't accept it + * :class:`~stem.connection.IncorrectCookieValue` if the cookie file's value + is rejected + * :class:`~stem.connection.UnrecognizedAuthChallengeMethod` if the Tor + client fails to recognize the AuthChallenge method + * :class:`~stem.connection.AuthChallengeUnsupported` if AUTHCHALLENGE is + unimplemented, or if unable to parse AUTHCHALLENGE response + * :class:`~stem.connection.AuthSecurityFailure` if AUTHCHALLENGE's response + looks like a security attack + * :class:`~stem.connection.InvalidClientNonce` if stem's AUTHCHALLENGE + client nonce is rejected for being invalid """ cookie_data = _read_cookie(cookie_path, True) @@ -661,16 +705,18 @@ def get_protocolinfo(controller): path is relative then we'll make an attempt (which may not work) to correct this (`ticket <https://trac.torproject.org/1101>`_). - This can authenticate to either a :class:`stem.control.BaseController` or - :class:`stem.socket.ControlSocket`. + This can authenticate to either a :class:`~stem.control.BaseController` or + :class:`~stem.socket.ControlSocket`. :param controller: tor controller or socket to be queried - :returns: :class:`stem.response.protocolinfo.ProtocolInfoResponse` provided by tor + :returns: :class:`~stem.response.protocolinfo.ProtocolInfoResponse` provided by tor :raises: - * :class:`stem.socket.ProtocolError` if the PROTOCOLINFO response is malformed - * :class:`stem.socket.SocketError` if problems arise in establishing or using the socket + * :class:`~stem.socket.ProtocolError` if the PROTOCOLINFO response is + malformed + * :class:`~stem.socket.SocketError` if problems arise in establishing or + using the socket """ try: @@ -715,7 +761,8 @@ def get_protocolinfo(controller): def _msg(controller, message): """ - Sends and receives a message with either a ControlSocket or BaseController. + Sends and receives a message with either a + :class:`~stem.socket.ControlSocket` or :class:`~stem.control.BaseController`. """ if isinstance(controller, stem.socket.ControlSocket): @@ -729,11 +776,14 @@ def _read_cookie(cookie_path, is_safecookie): Provides the contents of a given cookie file. :param str cookie_path: absolute path of the cookie file - :param bool is_safecookie: True if this was for SAFECOOKIE authentication, False if for COOKIE + :param bool is_safecookie: **True** if this was for SAFECOOKIE + authentication, **False** if for COOKIE :raises: - * :class:`stem.connection.UnreadableCookieFile` if the cookie file is unreadable - * :class:`stem.connection.IncorrectCookieSize` if the cookie size is incorrect (not 32 bytes) + * :class:`~stem.connection.UnreadableCookieFile` if the cookie file is + unreadable + * :class:`~stem.connection.IncorrectCookieSize` if the cookie size is + incorrect (not 32 bytes) """ if not os.path.exists(cookie_path): @@ -765,8 +815,8 @@ def _read_cookie(cookie_path, is_safecookie): def _expand_cookie_path(protocolinfo_response, pid_resolver, pid_resolution_arg): """ Attempts to expand a relative cookie path with the given pid resolver. This - leaves the cookie_path alone if it's already absolute, None, or the system - calls fail. + leaves the cookie_path alone if it's already absolute, **None**, or the + system calls fail. """ cookie_path = protocolinfo_response.cookie_path @@ -795,7 +845,8 @@ class AuthenticationFailure(Exception): """ Base error for authentication failures. - :var stem.socket.ControlMessage auth_response: AUTHENTICATE response from the control socket, None if one wasn't received + :var stem.socket.ControlMessage auth_response: AUTHENTICATE response from the + control socket, **None** if one wasn't received """ def __init__(self, message, auth_response = None): @@ -839,8 +890,10 @@ class CookieAuthFailed(AuthenticationFailure): Failure to authenticate with an authentication cookie. :param str cookie_path: location of the authentication cookie we attempted - :param bool is_safecookie: True if this was for SAFECOOKIE authentication, False if for COOKIE - :param stem.response.ControlMessage auth_response: reply to our authentication attempt + :param bool is_safecookie: **True** if this was for SAFECOOKIE + authentication, **False** if for COOKIE + :param stem.response.ControlMessage auth_response: reply to our + authentication attempt """ def __init__(self, message, cookie_path, is_safecookie, auth_response = None): @@ -903,7 +956,8 @@ class NoAuthCookie(MissingAuthInfo): """ PROTOCOLINFO response supports cookie auth but doesn't have its path. - :param bool is_safecookie: True if this was for SAFECOOKIE authentication, False if for COOKIE + :param bool is_safecookie: **True** if this was for SAFECOOKIE + authentication, **False** if for COOKIE """ def __init__(self, message, is_safecookie):
participants (1)
-
atagar@torproject.org