Skip to content

Commit

Permalink
Merge 474cd76 into 09a3632
Browse files Browse the repository at this point in the history
  • Loading branch information
meejah committed May 31, 2014
2 parents 09a3632 + 474cd76 commit 3974815
Show file tree
Hide file tree
Showing 15 changed files with 1,234 additions and 455 deletions.
17 changes: 16 additions & 1 deletion docs/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,23 @@ In the :file:`examples/` sub-directory are a few different
mostly-simple ways of using txtorcon. They all show how to set up a
connection and then wait for and use various information from Tor.

.. _hello_darkweb.py:

.. _dissalow_streams_by_port.py:
:file:`hello_darkweb.py`
------------------------

:download:`Download the example <../examples/hello_darkweb.py>`.

This is a minimal (but still working) hidden-service set up using the
endpoint parsers (these are Twisted ``IPlugin`` implementations; see
`the documentation
<https://twistedmatrix.com/documents/current/api/twisted.internet.endpoints.serverFromString.html>`_
for more). It even shows Tor's progress messages on the console.

.. literalinclude:: ../examples/hello_darkweb.py


.. _disallow_streams_by_port.py:

:file:`disallow_streams_by_port.py`
-----------------------------------
Expand Down
4 changes: 4 additions & 0 deletions docs/releases.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ unreleased

`git master <https://github.com/meejah/txtorcon>`_ *will likely become v0.9.3*

* In collaboration with `David Stainton <https://github.com/david415>`_ after a pull-request, we
have endpoint parser plugins for Twisted! This means code like
``serverFromString("onion:80").listen(...)`` is enough to start a
service. See the **4-line example** :ref:`hello-darkweb.py`

v0.9.2
------
Expand Down
Empty file modified examples/circuit_for_next_stream.py
100644 → 100755
Empty file.
24 changes: 24 additions & 0 deletions examples/hello_darkweb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env python

# This shows how to leverage the endpoints API to get a new hidden
# service up and running quickly. You can pass along this API to your
# users by accepting endpoint strings as per Twisted recommendations.
#
# http://twistedmatrix.com/documents/current/core/howto/endpoints.html#maximizing-the-return-on-your-endpoint-investment
#
# note that only the progress-updates needs the "import txtorcon" --
# you do still need it installed so that Twisted finds the endpoint
# parser plugin but code without knowledge of txtorcon can still
# launch a Tor instance using it. cool!

from __future__ import print_function
from twisted.internet import reactor, endpoints
from twisted.web import server, static
import txtorcon

res = static.Data("<html>Hello, hidden-service world!</html>", 'text/html')
ep = endpoints.serverFromString(reactor, "onion:80")
txtorcon.IProgressProvider(ep).add_progress_listener(lambda p, tag, msg: print(msg))
ep.listen(server.Site(res)).addCallback(lambda port: print(str(port.getHost()))).addErrback(print)

reactor.run()
86 changes: 51 additions & 35 deletions examples/launch_tor_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
##
## Here we set up a Twisted Web server and then launch a slave tor
## with a configured hidden service directed at the Web server we set
## up. This uses TCPHiddenServiceEndpoint, which gives you slightly
## less control over how things are set up, but may be easier. See
## also the :ref:`launch_tor.py` example.
## up. This uses serverFromString to translate the "onion" endpoint descriptor
## into a TCPHiddenServiceEndpoint object...
##


from twisted.internet import reactor
from twisted.web import server, resource
from twisted.internet.endpoints import serverFromString

import txtorcon


Expand All @@ -20,42 +20,58 @@ class Simple(resource.Resource):
def render_GET(self, request):
return "<html>Hello, world! I'm a hidden service!</html>"

site = server.Site(Simple())


def setup_failed(arg):
print "SETUP FAILED", arg
reactor.stop()


def setup_complete(port):
print "I have set up a hidden service, advertised at:"
print "http://%s:%d" % (port.onion_uri, port.onion_port)
print "locally listening on", port.getHost()


def setup_hidden_service(tor_process_protocol):
config = txtorcon.TorConfig(tor_process_protocol.tor_protocol)
public_port = 80
hs_endpoint = txtorcon.TCPHiddenServiceEndpoint(reactor, config,
public_port)

## the important thing here is that "site" implements
## IProtocolFactory -- this could be any service at all,
## obviously.
hs_endpoint.listen(site).addCallback(setup_complete).addErrback(setup_failed)


def updates(prog, tag, summary):
print "%d%%: %s" % (prog, summary)

# set a couple options to avoid conflict with the defaults if a Tor is
# already running
config = txtorcon.TorConfig()
config.SOCKSPort = 0
config.ControlPort = 9089

d = txtorcon.launch_tor(config, reactor, progress_updates=updates, timeout=60)
d.addCallback(setup_hidden_service)
# the port we get back should implement this (as well as IListeningPort)
port = txtorcon.IHiddenService(port)
print "I have set up a hidden service, advertised at:",
print "http://%s:%d" % (port.getHost().onion_uri, port.getHost().onion_port)
print "locally listening on", port.local_address.getHost()
print "Will stop in 60 seconds..."
def blam(x):
print "%d..." % x
reactor.callLater(50, blam, 10)
reactor.callLater(55, blam, 5)
reactor.callLater(56, blam, 4)
reactor.callLater(57, blam, 3)
reactor.callLater(58, blam, 2)
reactor.callLater(59, blam, 1)
reactor.callLater(60, reactor.stop)


def progress(percent, tag, message):
bar = int(percent / 10)
print '[%s%s] %s' % ('#' * bar, '.' * (10 - bar), message)

# several ways to proceed here and what they mean:
#
# ep0:
# launch a new Tor instance, configure a hidden service on some port and pubish descriptor for port 80
# ep1:
# connect to existing Tor via control-port 9051, configure a hidden
# service listening locally on 8080, publish a descriptor for port
# 80 and use an explicit hiddenServiceDir (where "hostname" and
# "private_key" files are put by Tor). We set SOCKS port explicitly, too.
# ep2:
# all the same as ep1, except we launch a new Tor (because no "controlPort=9051")
#

ep0 = "onion:80"
ep1 = "onion:80:controlPort=9051:localPort=8080:socksPort=9089:hiddenServiceDir=/home/human/src/txtorcon/hidserv"
ep2 = "onion:80:localPort=8080:socksPort=9089:hiddenServiceDir=/home/human/src/txtorcon/hidserv"

hs_endpoint = serverFromString(reactor, ep0)
txtorcon.IProgressProvider(hs_endpoint).add_progress_listener(progress)

# create our Web server and listen on the endpoint; this does the
# actual launching of (or connecting to) tor.
site = server.Site(Simple())
d = hs_endpoint.listen(site)
d.addCallback(setup_complete)
d.addErrback(setup_failed)

reactor.run()
52 changes: 52 additions & 0 deletions examples/launch_tor_endpoint2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env python

##
## Here we set up a Twisted Web server and then launch a slave tor
## with a configured hidden service directed at the Web server we set
## up. This uses serverFromString to translate the "onion" endpoint descriptor
## into a TCPHiddenServiceEndpoint object...
##

import shutil

from twisted.internet import reactor
from twisted.web import server, resource
from twisted.internet.endpoints import serverFromString

import txtorcon


class Simple(resource.Resource):
isLeaf = True

def render_GET(self, request):
return "<html>Hello, world! I'm a hidden service!</html>"

site = server.Site(Simple())


def setup_failed(arg):
print "SETUP FAILED", arg


def setup_complete(port):
print "Hidden serivce:", port.getHost()
print " locally at:", txtorcon.IHiddenService(port).local_address.getHost()

def progress(percent, tag, message):
bar = int(percent / 10)
print '[%s%s] %s' % ('#' * bar, '.' * (10 - bar), message)

hs_endpoint1 = serverFromString(reactor, "onion:80")
hs_endpoint2 = serverFromString(reactor, "onion:80")

txtorcon.IProgressProvider(hs_endpoint1).add_progress_listener(progress)
txtorcon.IProgressProvider(hs_endpoint2).add_progress_listener(progress)

d1 = hs_endpoint1.listen(site)
d2 = hs_endpoint2.listen(site)

d1.addCallback(setup_complete).addErrback(setup_failed)
d2.addCallback(setup_complete).addErrback(setup_failed)

reactor.run()
9 changes: 9 additions & 0 deletions examples/minimal_endpoint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env python

from __future__ import print_function
from twisted.internet import reactor
from twisted.internet.endpoints import serverFromString
from twisted.web import server, static

serverFromString(reactor, "onion:80").listen(server.Site(static.Data("Hello, world!", "text/plain"))).addCallback(print)
reactor.run()
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def pip_to_requirements(s):
author_email = __contact__,
url = __url__,
license = __license__,
packages = ["txtorcon"],
packages = ["txtorcon", "twisted.plugins"],
# scripts = ['examples/attach_streams_by_country.py'],

## I'm a little unclear if I'm doing this "properly", especially
Expand Down

0 comments on commit 3974815

Please sign in to comment.