1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
# Copyright (c) str4d <str4d@mail.i2p>
# See COPYING for details.
from builtins import object
from twisted.internet import interfaces
from zope.interface import implementer
from txi2p.bob.factory import BOBI2PClientFactory, BOBI2PServerFactory
def _validateDestination(dest):
# TODO: Validate I2P domain, B32 etc.
pass
@implementer(interfaces.IStreamClientEndpoint)
class BOBI2PClientEndpoint(object):
"""I2P client endpoint backed by the BOB API.
Args:
reactor: The client endpoint will be constructed with this reactor.
bobEndpoint (twisted.internet.interfaces.IStreamClientEndpoint): An
endpoint that will connect to the BOB API.
host (str): The I2P hostname or Destination to connect to.
port (int): The port to connect to inside I2P. If unset or `None`, the
default (null) port is used. Ignored because BOB doesn't support
ports yet.
tunnelNick (str): The tunnel nickname to use. If a tunnel with this
nickname already exists, it will be used. The default is ``txi2p-#``
where ``#`` is the PID of the current process.
* The implication of this is that by default, all endpoints (both
client and server) created by the same process will use the same
BOB tunnel.
inhost (str): The host that the tunnel created by BOB will listen on.
Defaults to ``localhost``.
inport (int): The port that the tunnel created by BOB will listen on.
Defaults to a port over 9000.
options (dict): I2CP options to configure the tunnel with.
"""
def __init__(self, reactor, bobEndpoint, dest,
port=None,
tunnelNick=None,
inhost='localhost',
inport=None,
options=None):
_validateDestination(dest)
self._reactor = reactor
self._bobEndpoint = bobEndpoint
self._dest = dest
self._port = port
self._tunnelNick = tunnelNick
self._inhost = inhost
self._inport = inport
self._options = options
def connect(self, fac):
"""Connect over I2P.
The provided factory will have its ``buildProtocol`` method called once
an I2P client tunnel has been successfully created.
If the factory's ``buildProtocol`` returns ``None``, the connection
will immediately close.
"""
i2pFac = BOBI2PClientFactory(self._reactor, fac, self._bobEndpoint, self._dest,
self._tunnelNick,
self._inhost,
self._inport,
self._options)
d = self._bobEndpoint.connect(i2pFac)
# Once the BOB IProtocol is returned, wait for the
# real IProtocol to be returned after tunnel creation,
# and pass it to any further registered callbacks.
d.addCallback(lambda proto: i2pFac.deferred)
return d
@implementer(interfaces.IStreamServerEndpoint)
class BOBI2PServerEndpoint(object):
"""I2P server endpoint backed by the BOB API.
Args:
reactor: The server endpoint will be constructed with this reactor.
bobEndpoint (twisted.internet.interfaces.IStreamClientEndpoint): An
endpoint that will connect to the BOB API.
keyfile (str): Path to a local file containing the keypair to use for
the server Destination. If non-existent, new keys will be generated
and stored.
port (int): The port to connect to inside I2P. If unset or `None`, the
default (null) port is used. Ignored because BOB doesn't support
ports yet.
tunnelNick (str): The tunnel nickname to use. If a tunnel with this
nickname already exists, it will be used. The default is ``txi2p-#``
where ``#`` is the PID of the current process.
* The implication of this is that by default, all endpoints (both
client and server) created by the same process will use the same
BOB tunnel.
outhost (str): The host that the tunnel created by BOB will forward data
to. Defaults to ``localhost``.
outport (int): The port that the tunnel created by BOB will forward data
to. Defaults to a port over 9000.
options (dict): I2CP options to configure the tunnel with.
"""
def __init__(self, reactor, bobEndpoint, keyfile,
port=None,
tunnelNick=None,
outhost='localhost',
outport=None,
options=None):
self._reactor = reactor
self._bobEndpoint = bobEndpoint
self._keyfile = keyfile
self._port = port
self._tunnelNick = tunnelNick
self._outhost = outhost
self._outport = outport
self._options = options
def listen(self, fac):
"""Listen over I2P.
The provided factory will have its ``buildProtocol`` method called once
an I2P server tunnel has been successfully created.
If the factory's ``buildProtocol`` returns ``None``, the connection
will immediately close.
"""
i2pFac = BOBI2PServerFactory(self._reactor, fac, self._bobEndpoint, self._keyfile,
self._tunnelNick,
self._outhost,
self._outport,
self._options)
d = self._bobEndpoint.connect(i2pFac)
# Once the BOB IProtocol is returned, wait for the
# IListeningPort to be returned after tunnel creation,
# and pass it to any further registered callbacks.
d.addCallback(lambda proto: i2pFac.deferred)
return d
|