diff options
-rwxr-xr-x | fot.py | 8 | ||||
-rw-r--r-- | ipv6.py | 127 |
2 files changed, 133 insertions, 2 deletions
@@ -9,7 +9,7 @@ import os, re from ConfigParser import ConfigParser -import login +import login, ipv6 config = ConfigParser() @@ -178,7 +178,11 @@ def start_server(server): print '%s' % server 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) print 'Starting per-network instances...' for server in (server for server in config.sections() if server.startswith('server/')): @@ -0,0 +1,127 @@ + +import socket +from twisted.internet import tcp +from twisted.internet import default +from twisted.internet import protocol +from twisted.internet import reactor + +from twisted.names.client import Resolver +resolver = Resolver('/etc/resolv.conf') + +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: + resolver.lookupIPV6Address(self.addr[0]).addCallbacks( + self.resolvedAddress, self.failIfNotConnected + ) + + def resolvedAddress(self, addr): + aaaas = [x for x in addr[0] if x.type == 28] # 28 = AAAA record + if not len(aaaas): + self.failIfNotConnected(Exception('Unable to resolve IPv6 address.')) + return + aaaa = aaaas[0].payload + self._setRealAddress(aaaa._address) + + 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() + |