summaryrefslogtreecommitdiff
path: root/ipv6.py
blob: 9dd1f322a8d9a58aea8fddef3cff44492ef08ac2 (plain)
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

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()