[Pkg-privacy-commits] [pyptlib] 49/136: Improve the code a bit.
Ximin Luo
infinity0 at moszumanska.debian.org
Sat Aug 22 13:25:06 UTC 2015
This is an automated email from the git hooks/post-receive script.
infinity0 pushed a commit to branch master
in repository pyptlib.
commit fcb2f4be8e18787738ecf359f04ae9ba49c09d9d
Author: George Kadianakis <desnacked at riseup.net>
Date: Tue Sep 18 18:16:18 2012 +0300
Improve the code a bit.
* Make better use of exceptions instead of relying on retvals.
* If Tor asks us for a transport we don't support, we now send back an
{S,C}METHOD-ERROR.
---
pyptlib/client.py | 49 +++++++++++++++---------------
pyptlib/client_config.py | 42 ++++++++++++-------------
pyptlib/config.py | 48 ++++++++++++-----------------
pyptlib/server.py | 52 +++++++++++++++++++------------
pyptlib/server_config.py | 79 +++++++++++++++++++++++++++++++-----------------
5 files changed, 149 insertions(+), 121 deletions(-)
diff --git a/pyptlib/client.py b/pyptlib/client.py
index 9486190..eccea49 100644
--- a/pyptlib/client.py
+++ b/pyptlib/client.py
@@ -1,13 +1,15 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
-""" The pyptlib.easy.client module includes a convenient API for writing pluggable transport clients. """
+"""
+This module provides a convenient API for writing pluggable transport clients.
+"""
from pyptlib.config import EnvException
from pyptlib.client_config import ClientConfig
-def init(transports):
+def init(supported_transports):
"""
Initialize the pluggable transport by parsing the environment
variables and generating output to report any errors. The given
@@ -20,45 +22,44 @@ def init(transports):
'state_loc' : Directory where the managed proxy should dump its
state files (if needed).
- 'transports' : The names of the transports that must be launched.
+ 'transports' : The names of the transports that must be
+ launched. The list can be empty.
- Returns None if something went wrong.
+ Throws EnvException.
"""
supportedTransportVersion = '1'
- try:
- config = ClientConfig()
- except EnvException:
- return None
+ config = ClientConfig()
if config.checkManagedTransportVersion(supportedTransportVersion):
config.writeVersion(supportedTransportVersion)
else:
config.writeVersionError()
- return None
-
- matchedTransports = []
- for transport in transports:
- if config.checkTransportEnabled(transport):
- matchedTransports.append(transport)
-
- # XXX the XXXs from server.py are valid here too.
+ raise EnvException("Unsupported managed proxy protocol version (%s)" %
+ str(config.getManagedTransportVersions()))
retval = {}
retval['state_loc'] = config.getStateLocation()
- retval['transports'] = matchedTransports
+ retval['transports'] = getTransportsList(supported_transports, config)
return retval
+def getTransportsList(supported_transports, config):
+ transports = []
+
+ if config.getAllTransportsEnabled():
+ return supported_transports
+
+ for transport in config.getClientTransports():
+ if transport in supported_transports:
+ transports.append(transport)
+ else:
+ config.writeMethodError(transport, "not supported")
+
+ return transports
-def reportSuccess(
- name,
- socksVersion,
- address,
- args,
- optArgs,
- ):
+def reportSuccess(name, socksVersion, address, args, optArgs):
"""
This method should be called to report when a transport has been successfully launched.
It generates output to Tor informing that the transport launched successfully and can be used.
diff --git a/pyptlib/client_config.py b/pyptlib/client_config.py
index 31cdaf5..4acc6f7 100644
--- a/pyptlib/client_config.py
+++ b/pyptlib/client_config.py
@@ -2,53 +2,50 @@
# -*- coding: utf-8 -*-
"""
- The pyptlib.client module contains a low-level API which closely follows the Tor Proposal 180: Pluggable transports for circumvention.
- This module inherits from pyptlib.config and contains just the parts of the API which are specific to the client implementations of the protocol.
+This module inherits from pyptlib.config and contains just the parts
+of the API which are specific to the client implementations of the
+protocol.
"""
-import os
-
from pyptlib.config import Config
__docformat__ = 'restructuredtext'
class ClientConfig(Config):
-
"""
- The ClientConfig class contains a low-level API which closely follows the Tor Proposal 180: Pluggable transports for circumvention.
- This class inherits from pyptlib.config.Config and contains just the parts of the API which are specific to the client implementations of the protocol.
+ This class inherits from pyptlib.config.Config and contains just
+ the parts of the API which are specific to the client
+ implementations of the protocol.
"""
# Public methods
- def __init__(self): # throws EnvError
+ def __init__(self):
"""
Initialize the ClientConfig object.
This causes the state location, managed transport, and transports version to be set.
+
+ Throws EnvException.
"""
Config.__init__(self)
- self.transports = self.get('TOR_PT_CLIENT_TRANSPORTS').split(','
- )
+ self.transports = self.get('TOR_PT_CLIENT_TRANSPORTS').split(',')
if '*' in self.transports:
self.allTransportsEnabled = True
self.transports.remove('*')
- def getClientTransports(self):
- """ Returns a list of strings representing the client transports reported by Tor. If present, '*' is stripped from this list and used to set allTransportsEnabled to True. """
+ def getClientTransports(self): # XXX why is this client-specific ???
+ """
+ Returns a list of strings representing the client transports
+ reported by Tor. If present, '*' is stripped from this list
+ and used to set allTransportsEnabled to True.
+ """
return self.transports
- def writeMethod( # CMETHOD
- self,
- name,
- socksVersion,
- address,
- args,
- optArgs,
- ):
+ def writeMethod(self, name, socksVersion, address, args, optArgs):
"""
Write a message to stdout specifying a supported transport
Takes: str, int, (str, int), [str], [str]
@@ -71,7 +68,10 @@ class ClientConfig(Config):
self.emit('CMETHOD-ERROR %s %s' % (name, message))
def writeMethodEnd(self): # CMETHODS DONE
- """ Write a message to stdout specifying that the list of supported transports has ended """
+ """
+ Write a message to stdout specifying that the list of
+ supported transports has ended.
+ """
self.emit('CMETHODS DONE')
diff --git a/pyptlib/config.py b/pyptlib/config.py
index 5889b70..b6d4e77 100644
--- a/pyptlib/config.py
+++ b/pyptlib/config.py
@@ -2,24 +2,14 @@
# -*- coding: utf-8 -*-
"""
- The pyptlib.config module contains a low-level API which closely follows the Tor Proposal 180: Pluggable transports for circumvention.
- This module contains the parts of the API which are shared by both client and server implementations of the protocol.
+This module contains parts of the managed proxy specification which
+are shared by both client and server implementations of the protocol.
"""
import os, sys
__docformat__ = 'restructuredtext'
-"""Receive "<addr>:<port>" in 'string', and return [<addr>,<port>]."""
-def parse_addrport(string):
- addrport = string.split(':')
-
- if (len(addrport) != 2):
- return None
- addrport[1] = int(addrport[1]) # XXX lame integer check
-
- return addrport
-
class Config:
"""
@@ -34,12 +24,16 @@ class Config:
# Public methods
- def __init__(self): # throws EnvError
- """ Initialize the Config object. this causes the state location and managed transport version to be set. """
+ def __init__(self):
+ """
+ Initialize the Config object. this causes the state location
+ and managed transport version to be set.
+
+ Throws EnvException.
+ """
self.stateLocation = self.get('TOR_PT_STATE_LOCATION')
- self.managedTransportVer = \
- self.get('TOR_PT_MANAGED_TRANSPORT_VER').split(',')
+ self.managedTransportVer = self.get('TOR_PT_MANAGED_TRANSPORT_VER').split(',')
def checkClientMode(self):
""" Check to see if the daemon is being run as a client or a server. This is determined by looking for the presence of the TOR_PT_CLIENT_TRANSPORTS environment variable. """
@@ -105,7 +99,11 @@ class Config:
return key in os.environ
def get(self, key):
- """ Attempts to fetch the given key from the environment variables. If it is present, it is returned, otherwise an EnvException is thrown. """
+ """
+ Attempts to fetch the given key from the environment
+ variables. If it is present, it is returned, otherwise an
+ EnvException is thrown.
+ """
if key in os.environ:
return os.environ[key]
@@ -118,15 +116,9 @@ class Config:
print msg
sys.stdout.flush()
-# Exception thrown when there is an error parsing the configuration parameters provided by Tor in environment variables
-
-class EnvException(Exception):
-
- """ The EnvException exception is thrown whenever a required environment variable is not presented or cannot be parsed. """
-
- message = None
-
- def __init__(self, message):
- self.message = message
-
+"""
+Exception thrown when there is an error parsing managed proxy
+environment variables. Also sends an ENV-ERROR to Tor.
+"""
+class EnvException(Exception): pass
diff --git a/pyptlib/server.py b/pyptlib/server.py
index b36ceee..bcc2ae8 100644
--- a/pyptlib/server.py
+++ b/pyptlib/server.py
@@ -7,7 +7,7 @@ from pyptlib.config import EnvException
from pyptlib.server_config import ServerConfig
-def init(transports):
+def init(supported_transports):
"""
Initialize the pluggable transport by parsing the environment
variables and generating output to report any errors. The
@@ -24,47 +24,59 @@ def init(transports):
of Tor's ORPort.
'ext_orport' : [<addr>, <port>] tuple containing the address and
- port of Tor's Extended ORPort.
+ port of Tor's Extended ORPort, or None if the Extended ORPort it's
+ not supported.
'transports' : A dictionary {<transport> : [<addr>, <port>]},
where <transport> is the name of the transport that must be
spawned, and [<addr>, <port>] is a list containing the location
- where that transport should bind.
+ where that transport should bind. The dictionary can be empty.
- Returns None if something went wrong.
+ Throws EnvException.
"""
supportedTransportVersion = '1'
- try:
- config = ServerConfig()
- except EnvException: # don't throw exceptions; return None
- return None
+ config = ServerConfig()
if config.checkManagedTransportVersion(supportedTransportVersion):
config.writeVersion(supportedTransportVersion)
else:
config.writeVersionError()
- return None
-
- matchedTransports = []
- for transport in transports:
- if config.checkTransportEnabled(transport):
- matchedTransports.append(transport)
-
- # XXX Must issue SMETHOD-ERROR when Tor asked us to spawn a
- # XXX transport but we don't support it!!!!
-
- # XXX what to do if matchedTransports is empty ???
+ raise EnvException("Unsupported managed proxy protocol version (%s)" %
+ str(config.getManagedTransportVersions()))
retval = {}
retval['state_loc'] = config.getStateLocation()
retval['orport'] = config.getORPort()
retval['ext_orport'] = config.getExtendedORPort()
- retval['transports'] = config.getServerBindAddresses()
+ retval['transports'] = getTransportsDict(supported_transports, config)
return retval
+def getTransportsDict(supported_transports, config):
+ """
+ Given the transport names that the managed proxy support in
+ 'transports', and Tor's configuration in 'config', figure out
+ which transports Tor wants us to spawn and create the appropriate
+ dictionary.
+ """
+ transports = {}
+
+ if config.getAllTransportsEnabled():
+ return config.getServerBindAddresses()
+
+ for transport in config.getServerTransports():
+ if transport in supported_transports:
+ assert(transport in config.getServerBindAddresses())
+ transports[transport] = config.getServerBindAddresses()[transport]
+ else:
+ # Issue SMETHOD-ERROR when Tor asks us to spawn a
+ # transport that we do not support.
+ config.writeMethodError(transport, "not supported")
+
+ return transports
+
def reportSuccess(name, address, options):
"""
This method should be called to report when a transport has been successfully launched.
diff --git a/pyptlib/server_config.py b/pyptlib/server_config.py
index 854b55b..181c071 100644
--- a/pyptlib/server_config.py
+++ b/pyptlib/server_config.py
@@ -2,8 +2,9 @@
# -*- coding: utf-8 -*-
"""
- The pyptlib.client module contains a low-level API which closely follows the Tor Proposal 180: Pluggable transports for circumvention.
- This module inherits from pyptlib.config and contains just the parts of the API which are specific to the server implementations of the protocol.
+This module inherits from pyptlib.config and contains just the parts
+of the API which are specific to the server implementations of the
+protocol.
"""
import os
@@ -13,36 +14,37 @@ import pyptlib.config as config
__docformat__ = 'restructuredtext'
class ServerConfig(config.Config):
-
"""
- The ServerConfig class contains a low-level API which closely follows the Tor Proposal 180: Pluggable transports for circumvention.
- This class inherits from pyptlib.config.Config and contains just the parts of the API which are specific to the client implementations of the protocol.
+ This class inherits from pyptlib.config.Config and contains just
+ the parts of the API which are specific to the client
+ implementations of the protocol.
"""
-
- extendedServerPort = None # TOR_PT_EXTENDED_SERVER_PORT
- ORPort = None # TOR_PT_ORPORT
- serverBindAddr = {} # TOR_PT_SERVER_BINADDR
-
# Public methods
- def __init__(self): # throws EnvError
+ def __init__(self):
"""
- Initialize the ClientConfig object.
- This causes the state location, managed transport, and transports version to be set.
+ Initialize the ClientConfig object.
+ This causes the state location, managed transport, and transports version to be set.
+
+ Throws EnvException.
"""
config.Config.__init__(self)
- # extendedORPort can also be 'None'
- self.extendedORPort = config.parse_addrport(self.get('TOR_PT_EXTENDED_SERVER_PORT'))
- self.ORPort = config.parse_addrport(self.get('TOR_PT_ORPORT'))
-
- if self.ORPort is None:
- raise config.EnvException("ORPort was corrupted")
+ # TOR_PT_EXTENDED_SERVER_PORT is optional; tor uses the empty
+ # string as its value if it does not support the Extended
+ # ORPort.
+ ext_orport_tmp = self.get('TOR_PT_EXTENDED_SERVER_PORT')
+ if ext_orport_tmp == '':
+ self.extendedORPort = None
+ else:
+ self.extendedORPort = self.get_addrport('TOR_PT_EXTENDED_SERVER_PORT')
+ self.ORPort = self.get_addrport('TOR_PT_ORPORT')
- binds = self.get('TOR_PT_SERVER_BINDADDR').split(',')
- for bind in binds:
+ self.serverBindAddr = {}
+ bindaddrs = self.get('TOR_PT_SERVER_BINDADDR').split(',')
+ for bind in bindaddrs:
(key, value) = bind.split('-')
self.serverBindAddr[key] = value.split(":") # XXX ugly code
self.serverBindAddr[key][1] = int(self.serverBindAddr[key][1]) # XXX ugly code
@@ -68,16 +70,15 @@ class ServerConfig(config.Config):
return self.serverBindAddr
def getServerTransports(self):
- """ Returns a list of strings representing the server transports reported by Tor. If present, '*' is stripped from this list and used to set allTransportsEnabled to True. """
+ """
+ Returns a list of strings representing the server
+ transports reported by Tor. If present, '*' is stripped from
+ this list and used to set allTransportsEnabled to True.
+ """
return self.transports
- def writeMethod( # SMETHOD
- self,
- name,
- address,
- options,
- ):
+ def writeMethod(self, name, address, options):
"""
Write a message to stdout specifying a supported transport
Takes: str, (str, int), MethodOptions
@@ -103,6 +104,28 @@ class ServerConfig(config.Config):
self.emit('SMETHODS DONE')
+ def get_addrport(self, key):
+ """
+ Given an environment variable name in 'key' with an
+ '<addr>:<port>' value, return [<addr>,<port>].
+
+ Throws EnvException.
+ """
+ string = self.get(key)
+
+ addrport = string.split(':')
+
+ if (len(addrport) != 2) or (not addrport[1].isdigit()):
+ message = '%s: Parsing error (%s).' % (key, string)
+ self.writeEnvError(message)
+ raise config.EnvException(message)
+
+ if (not 0 <= int(addrport[1]) < 65536):
+ message = '%s: Port out of range (%s).' % (key, string)
+ self.writeEnvError(message)
+ raise config.EnvException(message)
+
+ return addrport
class MethodOptions:
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-privacy/packages/pyptlib.git
More information about the Pkg-privacy-commits
mailing list