Created
January 9, 2013 00:16
-
-
Save thepaul/4489345 to your computer and use it in GitHub Desktop.
Simple cross-protocol forwarder (Twisted). Run under twistd -y with FWD_LISTEN and FWD_CONNECT set according to the rules for serverFromString (http://twistedmatrix.com/documents/current/api/twisted.internet.endpoints.html#serverFromString) and clientFromString (http://twistedmatrix.com/documents/current/api/twisted.internet.endpoints.html#clien…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
from twisted.internet import protocol, reactor, endpoints, error | |
from twisted.application import service | |
from twisted.python import log | |
class Forwarder(protocol.Protocol): | |
def __init__(self): | |
self.peer = None | |
self.peer_queue = [] | |
def dataReceived(self, data): | |
log.msg('received from %s: %r' % (self.transport.getPeer(), data)) | |
self.sendToPeer(data) | |
def peerConnected(self, peer): | |
self.peer = peer | |
sendme = self.peer_queue | |
self.peer_queue = [] | |
for data in sendme: | |
peer.dataFromPeer(data) | |
def dataFromPeer(self, data): | |
log.msg('writing to %s: %r' % (self.transport.getPeer(), data)) | |
self.transport.write(data) | |
def sendToPeer(self, data): | |
if self.peer is None: | |
self.peer_queue.append(data) | |
else: | |
self.peer.dataFromPeer(data) | |
def connectionMade(self): | |
log.msg('connected to %s' % self.transport.getPeer()) | |
if self.peer: | |
self.peer.peerConnected(self) | |
def connectionLost(self, reason): | |
if not reason.check(error.ConnectionDone): | |
log.err(reason, 'connection to %s lost' % self.transport.getPeer()) | |
if self.peer: | |
self.peer.peerConnectionLost(reason) | |
self.peer = None | |
self.transport = None | |
def peerConnectionFailed(self, reason): | |
if self.transport: | |
log.msg('closing because peer conn failed') | |
self.transport.loseConnection() | |
def peerConnectionLost(self, reason): | |
if self.transport: | |
log.msg('closing because peer conn was lost') | |
self.transport.loseConnection() | |
class ForwarderClientFactory(protocol.ClientFactory): | |
protocol = Forwarder | |
def __init__(self, other_end): | |
self.other_end = other_end | |
def buildProtocol(self, addr): | |
p = protocol.ClientFactory.buildProtocol(self, addr) | |
p.peer = self.other_end | |
del self.other_end | |
return p | |
class ForwarderServerFactory(protocol.ServerFactory): | |
protocol = Forwarder | |
clientFactory = ForwarderClientFactory | |
def __init__(self, forward_endpoint): | |
self.forward_endpoint = forward_endpoint | |
def connectClient(self, serverside): | |
clientfact = self.clientFactory(serverside) | |
d = self.forward_endpoint.connect(clientfact) | |
log.msg('started connecting to %s' % self.forward_endpoint) | |
d.addErrback(log.err, "connection to %s failed" | |
% self.forward_endpoint) | |
def buildProtocol(self, addr): | |
log.msg('connection from %s' % addr) | |
p = protocol.Factory.buildProtocol(self, addr) | |
self.connectClient(p) | |
return p | |
class ForwarderService(service.Service): | |
def __init__(self, server_endpoint, client_endpoint): | |
self.server_endpoint = server_endpoint | |
self.client_endpoint = client_endpoint | |
self.servport_d = None | |
def startService(self): | |
servfactory = ForwarderServerFactory(self.client_endpoint) | |
self.servport_d = self.server_endpoint.listen(servfactory) | |
def stopService(self): | |
if self.servport_d is not None: | |
return self.servport_d.addCallback(lambda p: p.stopListening()) | |
server_ep = endpoints.serverFromString(reactor, os.environ['FWD_LISTEN']) | |
client_ep = endpoints.clientFromString(reactor, os.environ['FWD_CONNECT']) | |
application = service.Application('Forwarder') | |
forwarder = ForwarderService(server_ep, client_ep) | |
forwarder.setServiceParent(application) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment