[Pkg-privacy-commits] [obfsproxy] 71/353: Fix transport callbacks to work with Twisted.
Ximin Luo
infinity0 at moszumanska.debian.org
Sat Aug 22 13:01:41 UTC 2015
This is an automated email from the git hooks/post-receive script.
infinity0 pushed a commit to branch master
in repository obfsproxy.
commit 2fceedb53e4a570f39128ed83b08af34f35f13d6
Author: George Kadianakis <desnacked at riseup.net>
Date: Wed Sep 26 20:16:04 2012 +0300
Fix transport callbacks to work with Twisted.
Also, document the callbacks.
---
obfsproxy/network/network.py | 66 +++++++++++++++++--------
obfsproxy/network/socks.py | 7 +++
obfsproxy/transports/base.py | 110 ++++++++++++------------------------------
obfsproxy/transports/dummy.py | 1 -
4 files changed, 85 insertions(+), 99 deletions(-)
diff --git a/obfsproxy/network/network.py b/obfsproxy/network/network.py
index d9e1f79..e267301 100644
--- a/obfsproxy/network/network.py
+++ b/obfsproxy/network/network.py
@@ -73,9 +73,10 @@ class Circuit(Protocol):
def __init__(self, transport):
self.transport = transport # takes a transport
+ self.downstream = None # takes a connection
+ self.upstream = None # takes a connection
- self.downstream = None # takes a twisted transport
- self.upstream = None # takes a twisted transport
+ self.closed = False # True if the circuit is closed.
self.name = "circ_%s" % hex(id(self))
@@ -88,11 +89,17 @@ class Circuit(Protocol):
assert(not self.downstream)
self.downstream = conn
- """We just completed the circuit, do a dummy dataReceived on
- the initiating connection in case it had any buffered data
- that must be flushed to the network."""
+ """We just completed the circuit.
+
+ Do a dummy dataReceived on the initiating connection in case
+ it has any buffered data that must be flushed to the network.
+
+ Also, call the transport-specific handshake method since this
+ is a good time to perform a handshake.
+ """
if self.circuitIsReady():
- self.upstream.dataReceived('')
+ self.upstream.dataReceived('') # XXX kind of a hack.
+ self.transport.handshake(self)
def setUpstreamConnection(self, conn):
"""
@@ -103,11 +110,17 @@ class Circuit(Protocol):
assert(not self.upstream)
self.upstream = conn
- """We just completed the circuit, do a dummy dataReceived on
- the initiating connection in case it had any buffered data
- that must be flushed to the network."""
+ """We just completed the circuit.
+
+ Do a dummy dataReceived on the initiating connection in case
+ it has any buffered data that must be flushed to the network.
+
+ Also, call the transport-specific handshake method since this
+ is a good time to perform a handshake.
+ """
if self.circuitIsReady():
self.downstream.dataReceived('')
+ self.transport.handshake(self)
def circuitIsReady(self):
"""
@@ -141,10 +154,15 @@ class Circuit(Protocol):
"""
Tear down the circuit.
"""
+ if self.closed: return # NOP if already closed
+
+ log.info("%s: Tearing down circuit." % self.name)
- log.info("%s: Closing down circuit." % self.name)
if self.downstream: self.downstream.close()
if self.upstream: self.upstream.close()
+ self.closed = True
+
+ self.transport.circuitDestroyed(self)
class StaticDestinationProtocol(Protocol):
"""
@@ -167,6 +185,8 @@ class StaticDestinationProtocol(Protocol):
self.circuit = circuit
self.direction = None # XXX currently unused
+ self.closed = False # True if connection is closed.
+
self.name = "conn_%s" % hex(id(self))
def connectionMade(self):
@@ -208,9 +228,11 @@ class StaticDestinationProtocol(Protocol):
def connectionLost(self, reason):
log.info("%s: Connection was lost (%s)." % (self.name, reason.getErrorMessage()))
+ self.circuit.close()
def connectionFailed(self, reason):
log.info("%s: Connection failed to connect (%s)." % (self.name, reason.getErrorMessage()))
+ self.circuit.close()
def dataReceived(self, data):
"""
@@ -221,7 +243,7 @@ class StaticDestinationProtocol(Protocol):
Circuit.setDownstreamConnection(). Document or split function.
"""
if (not self.buffer) and (not data):
- log.info("%s: dataReceived called without a reason.")
+ log.info("%s: dataReceived called without a reason.", self.name)
return
log.debug("%s: Received %d bytes (and %d cached):\n%s" \
@@ -238,12 +260,23 @@ class StaticDestinationProtocol(Protocol):
self.buffer = self.circuit.dataReceived(self.buffer + data, self)
def write(self, buf):
+ """
+ Write 'buf' to the underlying transport.
+ """
log.debug("%s: Writing %d bytes." % (self.name, len(buf)))
+
self.transport.write(buf)
def close(self):
+ """
+ Close the connection.
+ """
+ if self.closed: return # NOP if already closed
+
log.debug("%s: Closing connection." % self.name)
+
self.transport.loseConnection()
+ self.closed = True
class StaticDestinationClientFactory(Factory):
"""
@@ -264,12 +297,10 @@ class StaticDestinationClientFactory(Factory):
log.debug("%s: Client factory started connecting." % self.name)
def clientConnectionLost(self, connector, reason):
- log.info("%s: Connection was lost (%s)." % (self.name, reason.getErrorMessage()))
- self.circuit.close()
+ pass # connectionLost event is handled on the Protocol.
def clientConnectionFailed(self, connector, reason):
- log.debug("%s: Connection failed to connect (%s)." % (self.name, reason.getErrorMessage()))
- self.circuit.close()
+ pass # connectionFailed event is handled on the Protocol.
class StaticDestinationServerFactory(Factory):
"""
@@ -285,7 +316,6 @@ class StaticDestinationServerFactory(Factory):
mode: 'server' or 'client'
transport: the pluggable transport we should use to
obfuscate traffic on this connection.
- circuits: A list with all the circuits this listener has created.
"""
def __init__(self, remote_addrport, mode, transport):
@@ -296,9 +326,6 @@ class StaticDestinationServerFactory(Factory):
self.name = "fact_s_%s" % hex(id(self))
- # XXX currently unused. Remove to reduce memory fpr?
- self.circuits = []
-
assert(self.mode == 'client' or self.mode == 'server')
def startFactory(self):
@@ -308,7 +335,6 @@ class StaticDestinationServerFactory(Factory):
log.info("%s: New connection." % self.name)
circuit = Circuit(self.transport)
- self.circuits.append(circuit) # XXX when do we remove this?
# XXX instantiates a new factory for each client
clientFactory = StaticDestinationClientFactory(circuit, self.mode)
diff --git a/obfsproxy/network/socks.py b/obfsproxy/network/socks.py
index 20c05d6..46bd46d 100644
--- a/obfsproxy/network/socks.py
+++ b/obfsproxy/network/socks.py
@@ -87,6 +87,13 @@ class SOCKSv4Protocol(socks.SOCKSv4):
self.buffer = self.circuit.dataReceived(self.buffer + data, self)
+ def connectionLost(self, reason):
+ log.info("%s: Connection was lost (%s)." % (self.name, reason.getErrorMessage()))
+ self.circuit.close()
+
+ def connectionFailed(self, reason):
+ log.info("%s: Connection failed to connect (%s)." % (self.name, reason.getErrorMessage()))
+ self.circuit.close()
class SOCKSv4Factory(Factory):
"""
diff --git a/obfsproxy/transports/base.py b/obfsproxy/transports/base.py
index fcab386..f395b9b 100644
--- a/obfsproxy/transports/base.py
+++ b/obfsproxy/transports/base.py
@@ -4,15 +4,13 @@
import obfsproxy.common.log as log
"""
-This module contains BaseDaemon, a base class for implementing pluggable transport clients and server.
-It is not necessary to subclass BaseDaemon in order to implement pluggable transports.
-However, BaseDaemon provides utility methods that are useful for a variety of common transports.
+This module contains BaseDaemon, a pluggable transport skeleton class.
"""
def addrport(string):
"""
- Receive '<addr>:<port>' and return [<addr>,<port>]. Used during
- argparse CLI parsing.
+ Receive '<addr>:<port>' and return [<addr>,<port>].
+ Used during argparse CLI parsing.
"""
addrport = string.split(':')
@@ -24,14 +22,41 @@ def addrport(string):
return addrport
class BaseDaemon:
-
"""
- The BaseDaemon class is a skeleton class for implementing pluggable transports.
+ The BaseDaemon class is a skeleton class for pluggable transports.
+ It contains callbacks that your pluggable transports should
+ override and customize.
"""
def __init__(self):
pass
+ def handshake(self, circuit):
+ """
+ The Circuit 'circuit' was completed, and this is a good time
+ to do your transport-specific handshake on its downstream side.
+ """
+ pass
+
+ def circuitDestroyed(self, circuit):
+ """
+ Circuit 'circuit' was tore down.
+ Both connections of the circuit are closed when this callback triggers.
+ """
+ pass
+
+ def receivedDownstream(self, data, circuit):
+ """
+ Received 'data' in the downstream side of 'circuit'.
+ """
+ pass
+
+ def receivedUpstream(self, data, circuit):
+ """
+ Received 'data' in the upstream side of 'circuit'.
+ """
+ pass
+
@classmethod
def register_external_mode_cli(cls, subparser):
"""
@@ -63,74 +88,3 @@ class BaseDaemon:
return False
return True
-
- def read(
- self,
- socket,
- data,
- maxlen,
- ):
- """
- This read method is a convience method which takes a socket to read from, some existing data, and a maxlength.
- It reads bytes from socket and appends them to data until data is equal to maxlen, or the socket has no more bytes ready.
- It returns a new data object which is a combination of data and the bytes read from socket and which is <= maxlen.
- """
-
- remaining = maxlen - len(data)
- return data + socket.read(remaining)
-
- def checkTransition(
- self,
- data,
- maxlen,
- newState,
- ):
- """
- This is a convience method for state-based protocols which need to read fixed length data from the socket before they can change states.
- The checkTransition method takes some data, a max length, and state identifier.
- If len(data) == maxlen then the state is set to the state is set to newState and True is returned.
- Otherwise, the state stays the same and False is returned.
- """
-
- if len(data) == maxlen:
- state = newState
- return True
- else:
- return False
-
- def start(self):
- """
- This is the callback method which is called by the framework when a new connection has been made.
- In BaseDaemon it does nothing.
- It is overridden by subclasses.
- """
-
- pass
-
- # XXX update with the new API
- def receivedDownstream(self):
- """
- This is the callback method which is called by the framework when bytes have been received on the downstream socket.
- In BaseDaemon it does nothing.
- It is overridden by subclasses.
- """
-
- pass
-
- def receivedUpstream(self):
- """
- This is the callback method which is called by the framework when bytes have been received on the upstream socket.
- In BaseDaemon it does nothing.
- It is overridden by subclasses.
- """
-
- pass
-
- def end(self):
- """
- This is the callback method which is called by the framework when the connection is closed.
- In BaseDaemon it does nothing.
- It is overridden by subclasses.
- """
-
- pass
diff --git a/obfsproxy/transports/dummy.py b/obfsproxy/transports/dummy.py
index 8c52e90..706a358 100644
--- a/obfsproxy/transports/dummy.py
+++ b/obfsproxy/transports/dummy.py
@@ -7,7 +7,6 @@ from obfsproxy.transports.base import BaseDaemon
class DummyDaemon(BaseDaemon):
-
"""
DummyDaemon is the base class for DummyClient and DummyServer.
Since the protocol is so simple, DummyDaemon provides all of the
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-privacy/packages/obfsproxy.git
More information about the Pkg-privacy-commits
mailing list