[Pkg-privacy-commits] [Git][pkg-privacy-team/txtorcon][upstream] New upstream version 19.0.0
Iain Learmonth
irl at debian.org
Thu Jun 13 22:24:40 BST 2019
Iain Learmonth pushed to branch upstream at Privacy Maintainers / txtorcon
Commits:
d1e66fa1 by Iain R. Learmonth at 2019-06-13T21:09:26Z
New upstream version 19.0.0
- - - - -
16 changed files:
- Makefile
- PKG-INFO
- README.rst
- docs/release-checklist.rst
- docs/releases.rst
- examples/connect.py
- test/test_controller.py
- test/test_torcontrolprotocol.py
- test/test_torstate.py
- txtorcon.egg-info/PKG-INFO
- txtorcon/_metadata.py
- txtorcon/controller.py
- txtorcon/onion.py
- txtorcon/torconfig.py
- txtorcon/torcontrolprotocol.py
- txtorcon/torstate.py
Changes:
=====================================
Makefile
=====================================
@@ -1,6 +1,6 @@
.PHONY: test html counts coverage sdist clean install doc integration diagrams
default: test
-VERSION = 18.3.0
+VERSION = 19.0.0
test:
PYTHONPATH=. trial --reporter=text test
=====================================
PKG-INFO
=====================================
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: txtorcon
-Version: 18.3.0
+Version: 19.0.0
Summary:
Twisted-based Tor controller client, with state-tracking and
configuration abstractions.
@@ -44,10 +44,6 @@ Description:
:target: https://txtorcon.readthedocs.io/en/latest
:alt: ReadTheDocs
- .. image:: http://api.flattr.com/button/flattr-badge-large.png
- :target: http://flattr.com/thing/1689502/meejahtxtorcon-on-GitHub
- :alt: flattr
-
.. image:: https://landscape.io/github/meejah/txtorcon/master/landscape.svg?style=flat
:target: https://landscape.io/github/meejah/txtorcon/master
:alt: Code Health
=====================================
README.rst
=====================================
@@ -31,10 +31,6 @@
:target: https://txtorcon.readthedocs.io/en/latest
:alt: ReadTheDocs
-.. image:: http://api.flattr.com/button/flattr-badge-large.png
- :target: http://flattr.com/thing/1689502/meejahtxtorcon-on-GitHub
- :alt: flattr
-
.. image:: https://landscape.io/github/meejah/txtorcon/master/landscape.svg?style=flat
:target: https://landscape.io/github/meejah/txtorcon/master
:alt: Code Health
=====================================
docs/release-checklist.rst
=====================================
@@ -23,7 +23,7 @@ Release Checklist
* update heading, date
* on both signing-machine and build-machine shells:
- * export VERSION=18.0.0
+ * export VERSION=19.0.0
* (if on signing machine) "make dist" and "make dist-sigs"
* creates:
=====================================
docs/releases.rst
=====================================
@@ -15,11 +15,22 @@ that will be "19.2.1".
See also :ref:`api_stability`.
-
unreleased
----------
-`git master <https://github.com/meejah/txtorcon>`_ *will likely become v19.0.0*
+`git master <https://github.com/meejah/txtorcon>`_ *will likely become v19.1.0*
+
+
+v19.0.0
+-------
+
+January 15, 2019
+
+ * `txtorcon-19.0.0.tar.gz <http://timaq4ygg2iegci7.onion/txtorcon-19.0.0.tar.gz>`_ (`PyPI <https://pypi.python.org/pypi/txtorcon/19.0.0>`_ (:download:`local-sig </../signatues/txtorcon-19.0.0.tar.gz.asc>` or `github-sig <https://github.com/meejah/txtorcon/blob/master/signatues/txtorcon-19.0.0.tar.gz.asc?raw=true>`_) (`source <https://github.com/meejah/txtorcon/archive/v19.0.0.tar.gz>`_)
+ * add :func:`TorControlProtocol.when_disconnected` (will replace `.on_disconnect`)
+ * add `detach=` kwarg to :func:`Tor.create_onion_service`
+ * add `purpose=` kwarg to :func:`TorState.build_circuit`
+
v18.3.0
-------
=====================================
examples/connect.py
=====================================
@@ -16,9 +16,11 @@ def main(reactor):
tor = yield txtorcon.connect(reactor, ep)
print("Connected to Tor {version}".format(version=tor.protocol.version))
- state = yield tor.create_state()
- # or:
- # state = yield txtorcon.TorState.from_protocol(tor.protocol)
- print("Tor state created. Circuits:")
- for circuit in state.circuits.values():
- print(" {circuit.id}: {circuit.path}".format(circuit=circuit))
+ d = tor.protocol.when_disconnected()
+
+ def its_gone(value):
+ print("Connection gone")
+ d.addCallback(its_gone)
+
+ tor.protocol.transport.loseConnection()
+ yield d
=====================================
test/test_controller.py
=====================================
@@ -3,7 +3,7 @@ import six
import functools
from os.path import join
from mock import Mock, patch
-from six.moves import StringIO
+from io import BytesIO
from twisted.internet.interfaces import IReactorCore
from twisted.internet.interfaces import IListeningPort
@@ -51,7 +51,7 @@ class FakeProcessTransport(proto_helpers.StringTransportWithDisconnection):
)
def closeStdin(self):
- self.process_protocol.outReceived(b"Bootstrap")
+ self.process_protocol.outReceived(b"Opening Control listener")
return
@@ -570,12 +570,12 @@ class LaunchTorTests(unittest.TestCase):
return proto.post_bootstrap
def on_protocol(proto):
- proto.errReceived('Something went horribly wrong!\n')
+ proto.errReceived(b'Something went horribly wrong!\n')
trans = FakeProcessTransport()
trans.protocol = Mock()
- fakeout = StringIO()
- fakeerr = StringIO()
+ fakeout = BytesIO()
+ fakeerr = BytesIO()
creator = functools.partial(connector, Mock(), Mock())
try:
yield launch(
@@ -587,8 +587,8 @@ class LaunchTorTests(unittest.TestCase):
)
self.fail() # should't get callback
except RuntimeError as e:
- self.assertEqual('', fakeout.getvalue())
- self.assertEqual('Something went horribly wrong!\n', fakeerr.getvalue())
+ self.assertEqual(b'', fakeout.getvalue())
+ self.assertEqual(b'Something went horribly wrong!\n', fakeerr.getvalue())
self.assertTrue(
'Something went horribly wrong!' in str(e)
)
@@ -599,7 +599,7 @@ class LaunchTorTests(unittest.TestCase):
trans = FakeProcessTransport()
def on_protocol(proto):
- proto.outReceived(b'Bootstrapped 100%\n')
+ proto.outReceived(b'Opening Control listener\n')
reactor = FakeReactor(self, trans, on_protocol, [1, 2, 3])
fails = ['one']
=====================================
test/test_torcontrolprotocol.py
=====================================
@@ -215,6 +215,38 @@ class DisconnectionTests(unittest.TestCase):
self.protocol.connectionLost(f)
self.assertTrue(it_was_called.yes)
+ def test_when_disconnect(self):
+ """
+ see that we get our callback for when_disconnected if the
+ transport goes away
+ """
+ def it_was_called(arg):
+ it_was_called.yes = True
+ return None
+ it_was_called.yes = False
+
+ d = self.protocol.when_disconnected()
+ d.addCallback(it_was_called)
+ f = failure.Failure(error.ConnectionDone("It's all over"))
+ self.protocol.connectionLost(f)
+ self.assertTrue(it_was_called.yes)
+
+ def test_when_disconnect_error(self):
+ """
+ see that we get our errback for when_disconnected if the
+ transport goes away
+ """
+ def it_was_called(arg):
+ it_was_called.yes = True
+ return None
+ it_was_called.yes = False
+
+ d = self.protocol.when_disconnected()
+ d.addErrback(it_was_called)
+ f = failure.Failure(RuntimeError("sadness"))
+ self.protocol.connectionLost(f)
+ self.assertTrue(it_was_called.yes)
+
def test_disconnect_errback(self):
"""
see that we get our callback on_disconnect if the transport
=====================================
test/test_torstate.py
=====================================
@@ -1399,7 +1399,6 @@ s Fast Guard Running Stable Valid
circ = FakeCircuit()
def _build(*args, **kw):
- print("DING {} {}".format(args, kw))
return defer.succeed(circ)
self.state.build_circuit = _build
@@ -1411,7 +1410,6 @@ s Fast Guard Running Stable Valid
# be closed
d = build_timeout_circuit(self.state, clock, path, timeout, using_guards=False)
clock.advance(1)
- print("DING {}".format(self.state))
d.cancel()
with self.assertRaises(CircuitBuildTimedOutError):
@@ -1509,3 +1507,30 @@ s Fast Guard Running Stable Valid
d.addErrback(check_reason)
return d
+
+ def test_build_circuit_with_purpose(self):
+ class FakeRouter:
+ def __init__(self, i):
+ self.id_hex = i
+ self.flags = []
+
+ path = []
+ for x in range(3):
+ path.append(FakeRouter("$%040d" % x))
+ path[0].flags = ['guard']
+
+ d = self.state.build_circuit(path, using_guards=True, purpose="general")
+ d.addCallback(self.circuit_callback)
+
+ self.assertEqual(self.transport.value(), b'EXTENDCIRCUIT 0 0000000000000000000000000000000000000000,0000000000000000000000000000000000000001,0000000000000000000000000000000000000002 purpose=general\r\n')
+ self.send(b"250 EXTENDED 1234")
+ # we can't just .send(b'650 CIRC 1234 BUILT') this because we
+ # didn't fully hook up the protocol to the state, e.g. via
+ # post_bootstrap etc.
+ self.state.circuits[1234].update(['1234', 'FAILED', 'REASON=TIMEOUT'])
+
+ def check_reason(fail):
+ self.assertEqual(fail.value.reason, 'TIMEOUT')
+ d.addErrback(check_reason)
+
+ return d
=====================================
txtorcon.egg-info/PKG-INFO
=====================================
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: txtorcon
-Version: 18.3.0
+Version: 19.0.0
Summary:
Twisted-based Tor controller client, with state-tracking and
configuration abstractions.
@@ -44,10 +44,6 @@ Description:
:target: https://txtorcon.readthedocs.io/en/latest
:alt: ReadTheDocs
- .. image:: http://api.flattr.com/button/flattr-badge-large.png
- :target: http://flattr.com/thing/1689502/meejahtxtorcon-on-GitHub
- :alt: flattr
-
.. image:: https://landscape.io/github/meejah/txtorcon/master/landscape.svg?style=flat
:target: https://landscape.io/github/meejah/txtorcon/master
:alt: Code Health
=====================================
txtorcon/_metadata.py
=====================================
@@ -1,6 +1,6 @@
-__version__ = '18.3.0'
+__version__ = '19.0.0'
__author__ = 'meejah'
__contact__ = 'meejah at meejah.ca'
__url__ = 'https://github.com/meejah/txtorcon'
__license__ = 'MIT'
-__copyright__ = 'Copyright 2012-2018'
+__copyright__ = 'Copyright 2012-2019'
=====================================
txtorcon/controller.py
=====================================
@@ -945,7 +945,9 @@ class Tor(object):
# method names are kind of long (not-ideal)
@inlineCallbacks
- def create_onion_service(self, ports, private_key=None, version=3, progress=None, await_all_uploads=False, single_hop=None):
+ def create_onion_service(self, ports, private_key=None, version=3,
+ progress=None, await_all_uploads=False,
+ single_hop=None, detach=None):
"""
Create a new Onion service
@@ -986,6 +988,12 @@ class Tor(object):
that Tor options `HiddenServiceSingleHopMode`,
`HiddenServiceNonAnonymousMode` must be set to `1` and there
must be no `SOCKSPort` configured for this to actually work.
+
+ :param detach: if True, the created service won't be tied to
+ this control connection and will still be active when this
+ control-connection goes away (this means the service will
+ appear in `GETINFO onions/detached` to all other
+ controllers)
"""
if version not in (2, 3):
raise ValueError(
@@ -1005,6 +1013,7 @@ class Tor(object):
progress=progress,
await_all_uploads=await_all_uploads,
single_hop=single_hop,
+ detach=detach,
)
returnValue(service)
@@ -1234,7 +1243,7 @@ class TorProcessProtocol(protocol.ProcessProtocol):
# tor_connection_failed)
txtorlog.msg(data)
if not self.attempted_connect and self.connection_creator \
- and b'Bootstrap' in data:
+ and b'Opening Control listener' in data:
self.attempted_connect = True
# hmmm, we don't "do" anything with this Deferred?
# (should it be connected to the when_connected
@@ -1273,7 +1282,8 @@ class TorProcessProtocol(protocol.ProcessProtocol):
if self.kill_on_stderr:
self.transport.loseConnection()
raise RuntimeError(
- "Received stderr output from slave Tor process: " + data)
+ "Received stderr output from slave Tor process: " + data.decode('utf8')
+ )
def cleanup(self):
"""
=====================================
txtorcon/onion.py
=====================================
@@ -1118,7 +1118,6 @@ class FilesystemAuthenticatedOnionService(object):
config.HiddenServices.append(fhs)
def translate_progress(pct, tag, description):
- print("OHAI {} {}".format(pct, tag))
# XXX fixme actually translate..
if progress:
progress(pct, tag, description)
=====================================
txtorcon/torconfig.py
=====================================
@@ -1104,7 +1104,7 @@ class TorConfig(object):
# then...?)
try:
ephemeral = yield self.protocol.get_info('onions/current')
- except Exception as e:
+ except Exception:
self.config['EphemeralOnionServices'] = []
else:
onions = []
=====================================
txtorcon/torcontrolprotocol.py
=====================================
@@ -23,7 +23,7 @@ from txtorcon.log import txtorlog
from txtorcon.interface import ITorControlProtocol
from .spaghetti import FSM, State, Transition
-from .util import maybe_coroutine
+from .util import maybe_coroutine, SingleObserver
DEFAULT_VALUE = 'DEFAULT'
@@ -271,6 +271,11 @@ class TorControlProtocol(LineOnlyReceiver):
there was an error, the errback is called instead.
"""
+ self._when_disconnected = SingleObserver()
+ """
+ Private. See :func:`.when_disconnected`
+ """
+
self.post_bootstrap = defer.Deferred()
"""
This Deferred is triggered when we're done setting up
@@ -648,6 +653,13 @@ class TorControlProtocol(LineOnlyReceiver):
self._maybe_issue_command()
return d
+ def when_disconnected(self):
+ """
+ :returns: a Deferred that fires when (if) we disconnect from our
+ Tor process.
+ """
+ return self._when_disconnected.when_fired()
+
# the remaining methods are internal API implementations,
# callbacks and state-tracking methods -- you shouldn't have any
# need to call them.
@@ -672,11 +684,17 @@ class TorControlProtocol(LineOnlyReceiver):
def connectionLost(self, reason):
"Protocol API"
txtorlog.msg('connection terminated: ' + str(reason))
+ if reason.check(ConnectionDone):
+ self._when_disconnected.fire(self)
+ else:
+ self._when_disconnected.fire(reason)
+
# ...and this is why we don't do on_disconnect = Deferred() :(
# and instead should have had on_disconnect() method that
# returned a new Deferred to each caller..(we're checking if
# this Deferred has any callbacks because if it doesn't we'll
# generate an "Unhandled error in Deferred")
+ # XXX (deprecate this)
if not self.on_disconnect.called and self.on_disconnect.callbacks:
if reason.check(ConnectionDone):
self.on_disconnect.callback(self)
=====================================
txtorcon/torstate.py
=====================================
@@ -545,7 +545,7 @@ class TorState(object):
circ.update([str(circ_id), 'EXTENDED'])
return circ
- def build_circuit(self, routers=None, using_guards=True):
+ def build_circuit(self, routers=None, using_guards=True, purpose=None):
"""
Builds a circuit consisting of exactly the routers specified,
in order. This issues an EXTENDCIRCUIT call to Tor with all
@@ -586,6 +586,9 @@ class TorState(object):
cmd += router.decode('utf8')
else:
cmd += router.id_hex[1:]
+
+ if purpose is not None:
+ cmd += " purpose={}".format(purpose)
d = self.protocol.queue_command(cmd)
d.addCallback(self._find_circuit_after_extend)
return d
View it on GitLab: https://salsa.debian.org/pkg-privacy-team/txtorcon/commit/d1e66fa15354b5e0bc723ebf0c5d58dbbf49b09d
--
View it on GitLab: https://salsa.debian.org/pkg-privacy-team/txtorcon/commit/d1e66fa15354b5e0bc723ebf0c5d58dbbf49b09d
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-privacy-commits/attachments/20190613/a92a4ab5/attachment-0001.html>
More information about the Pkg-privacy-commits
mailing list