From b97e85feef6b4dad4add23d17e37fd5ee976e1e3 Mon Sep 17 00:00:00 2001 From: Jon Bergli Heier Date: Mon, 24 May 2010 22:04:07 +0200 Subject: Added IPv6 support. This currently needs the destination host to be stored in host6. The local address can be bound by setting bind6. --- fot.py | 10 ++++-- ipv6.py | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 ipv6.py diff --git a/fot.py b/fot.py index 8412e8c..75cdfaf 100755 --- a/fot.py +++ b/fot.py @@ -9,7 +9,7 @@ import os from ConfigParser import ConfigParser -import login +import login, ipv6 config = ConfigParser() @@ -130,9 +130,13 @@ for server in (server for server in config.sections() if server.startswith('serv ch = [x[0] for x in ms if c in x[1]] channels.append('%s (%s)' % (c, ' '.join(ch))) print '%s: %s' % (server, ' '.join(channels)) - del channels, ms, c, ch, x + #del channels, ms, c, ch, x factory = BotFactory(server, config.get(server, 'nickname')) - reactor.connectTCP(config.get(server, 'host'), config.getint(server, 'port'), factory) + if config.has_option(server, 'host6'): + bind6 = (config.get(server, 'bind6'), 0) if config.has_option(server, 'bind6') else None + ipv6.connectTCP6(config.get(server, 'host6'), config.getint(server, 'port6'), factory, bindAddress = bind6) + else: + reactor.connectTCP(config.get(server, 'host'), config.getint(server, 'port'), factory) loginfactory = login.getManholeFactory(globals(), os.path.expanduser('~/.fot.users')) reactor.listenTCP(3333, loginfactory) diff --git a/ipv6.py b/ipv6.py new file mode 100644 index 0000000..eb6ce2e --- /dev/null +++ b/ipv6.py @@ -0,0 +1,116 @@ + +import socket +from twisted.internet import tcp +from twisted.internet import default +from twisted.internet import protocol +from twisted.internet import reactor + +class IPv6Address(object): + def __init__(self, type, host, port, flowInfo, scope): + self.type = type + self.host = host + self.port = port + self.flowInfo = flowInfo + self.scope = scope + + def __eq__(self, other): + if isinstance(other, IPv6Address): + a = (self.type, self.host, self.port, self.flowInfo, self.scope) + b = (other.type, other.host, other.port, other.flowInfo, other.scope) + return a == b + return False + + def __str__(self): + return 'IPv6Address(%s, %r, %d, %d, %d)' % ( + self.type, self.host, self.port, self.flowInfo, self.scope) + +def isIPv6Address(ip): + try: + socket.inet_pton(socket.AF_INET6, ip) + except: + return 0 + return 1 + +class Client(tcp.Client): + addressFamily = socket.AF_INET6 + + def resolveAddress(self): + if isIPv6Address(self.addr[0]): + self._setRealAddress(self.addr[0]) + else: + reactor.resolve(self.addr[0]).addCallbacks( + self._setRealAddress, self.failIfNotConnected + ) + + def getHost(self): + return IPv6Address('TCP', *self.socket.getsockname()) + + def getPeer(self): + return IPv6Address('TCP', *self.socket.getpeername()) + + +class Connector(tcp.Connector): + def _makeTransport(self): + return Client(self.host, self.port, self.bindAddress, self, self.reactor) + + def getDestination(self): + return IPv6Address('TCP', self.host, self.port) + +class Server(tcp.Server): + def getHost(self): + return IPv6Address('TCP', *self.socket.getsockname()) + + def getPeer(self): + return IPv6Address('TCP', *self.client) + +class Port(tcp.Port): + addressFamily = socket.AF_INET6 + + transport = Server + + def _buildAddr(self, address): + return IPv6Address('TCP', *address) + + def getHost(self): + return IPv6Address('TCP', *self.socket.getsockname()) + + def getPeer(self): + return IPv6Address('TCP', *self.socket.getpeername()) + +def connectTCP6(host, port, factory, timeout=30, bindAddress=None, reactor=None): + if reactor is None: + from twisted.internet import reactor + return reactor.connectWith( + Connector, host, port, factory, timeout, bindAddress + ) + + +def listenTCP6(port, factory, backlog=5, interface='::', reactor=None): + if reactor is None: + from twisted.internet import reactor + return reactor.listenWith(Port, port, factory, backlog, interface) + +def main(): + from twisted.internet import reactor + + class TrivialProtocol(protocol.Protocol): + def connectionMade(self): + print 'I (', self.transport.getHost(), ') am connected! (to ', self.transport.getPeer(), ')' + self.transport.write('Hello, world!\n') + + def dataReceived(self, data): + print 'Received: ' + repr(data) + + class TrivialServerFactory(protocol.ServerFactory): + protocol = TrivialProtocol + class TrivialClientFactory(protocol.ClientFactory): + protocol = TrivialProtocol + + p = listenTCP6(6666, TrivialServerFactory()) + c = connectTCP6('::1', 6666, TrivialClientFactory()) + + reactor.run() + +if __name__ == '__main__': + main() + -- cgit v1.2.3