2 Generic NAT Port mapping interface.
6 @author: Raphael Slinckx
7 @copyright: Copyright 2005
9 @contact: U{raphael@slinckx.net<mailto:raphael@slinckx.net>}
15 from twisted.internet.base import BasePort
18 def get_port_mapper(proto="TCP"):
20 Returns a L{NATMapper} instance, suited to map a port for
21 the given protocol. Defaults to TCP.
23 For the moment, only upnp mapper is available. It accepts both UDP and TCP.
25 @param proto: The protocol: 'TCP' or 'UDP'
27 @return: A deferred called with a L{NATMapper} instance
28 @rtype: L{twisted.internet.defer.Deferred}
30 import nattraverso.pynupnp
31 return nattraverso.pynupnp.get_port_mapper()
35 Define methods to map port objects (as returned by twisted's listenXX).
36 This allows NAT to be traversed from incoming packets.
38 Currently the only implementation of this class is the UPnP Mapper, which
39 can map UDP and TCP ports, if an UPnP Device exists.
42 raise NotImplementedError("Cannot instantiate the class")
46 Create a mapping for the given twisted's port object.
48 The deferred will call back with a tuple (extaddr, extport):
49 - extaddr: The ip string of the external ip address of this host
50 - extport: the external port number used to map the given Port object
52 When called multiple times with the same Port,
53 callback with the existing mapping.
55 @param port: The port object to map
56 @type port: a L{twisted.internet.interfaces.IListeningPort} object
57 @return: A deferred called with the above defined tuple
58 @rtype: L{twisted.internet.defer.Deferred}
60 raise NotImplementedError
64 Returns the existing mapping for the given port object. That means map()
65 has to be called before.
67 @param port: The port object to retreive info from
68 @type port: a L{twisted.internet.interfaces.IListeningPort} object
69 @raise ValueError: When there is no such existing mapping
70 @return: a tuple (extaddress, extport).
71 @see: L{map() function<map>}
73 raise NotImplementedError
75 def unmap(self, port):
77 Remove an existing mapping for the given twisted's port object.
79 @param port: The port object to unmap
80 @type port: a L{twisted.internet.interfaces.IListeningPort} object
81 @return: A deferred called with None
82 @rtype: L{twisted.internet.defer.Deferred}
83 @raise ValueError: When there is no such existing mapping
85 raise NotImplementedError
87 def get_port_mappings(self):
89 Returns a deferred that will be called with a dictionnary of the
92 The dictionnary structure is the following:
93 - Keys: tuple (protocol, external_port)
94 - protocol is "TCP" or "UDP".
95 - external_port is the external port number, as see on the
97 - Values:tuple (internal_ip, internal_port)
98 - internal_ip is the LAN ip address of the host.
99 - internal_port is the internal port number mapped
102 @return: A deferred called with the above defined dictionnary
103 @rtype: L{twisted.internet.defer.Deferred}
105 raise NotImplementedError
107 def _check_valid_port(self, port):
108 """Various Port object validity checks. Raise a ValueError."""
109 if not isinstance(port, BasePort):
110 raise ValueError("expected a Port, got %r"%(port))
112 if not port.connected:
113 raise ValueError("Port %r is not listening"%(port))
115 loc_addr = port.getHost()
116 if loc_addr.port == 0:
117 raise ValueError("Port %r has port number of 0"%(port))