add UPnP-IGD feature to ask our router to forward port.

This commit is contained in:
Yann Leboulanger 2011-08-24 11:04:31 +02:00
parent be6ee39a3b
commit dcb5df4b8a
3 changed files with 96 additions and 2 deletions

View File

@ -179,6 +179,15 @@ try:
except ImportError:
HAVE_FARSIGHT = False
HAVE_UPNP_IGD = True
try:
import gupnp.igd
gupnp_igd = gupnp.igd.Simple()
except ImportError:
HAVE_UPNP_IGD = False
gajim_identity = {'type': 'pc', 'category': 'client', 'name': 'Gajim'}
gajim_common_features = [xmpp.NS_BYTESTREAM, xmpp.NS_SI, xmpp.NS_FILE,
xmpp.NS_MUC, xmpp.NS_MUC_USER, xmpp.NS_MUC_ADMIN, xmpp.NS_MUC_OWNER,

View File

@ -349,8 +349,8 @@ class ConnectionSocks5Bytestream(ConnectionBytestream):
self._add_addiditional_streamhosts_to_query(query, file_props)
self._add_local_ips_as_streamhosts_to_query(query, file_props)
self._add_proxy_streamhosts_to_query(query, file_props)
self.connection.send(iq)
self._add_upnp_igd_as_streamhost_to_query(query, file_props, iq)
# Upnp-igd is ascynchronous, so it will send the iq itself
def _add_streamhosts_to_query(self, query, sender, port, hosts):
for host in hosts:
@ -386,6 +386,84 @@ class ConnectionSocks5Bytestream(ConnectionBytestream):
additional_hosts = []
self._add_streamhosts_to_query(query, sender, port, additional_hosts)
def _add_upnp_igd_as_streamhost_to_query(self, query, file_props, iq):
if not gajim.HAVE_UPNP_IGD:
self.connection.send(iq)
return
def ip_is_local(ip):
if '.' not in ip:
# it's an IPv6
return True
ip_s = ip.split('.')
ip_l = long(ip_s[0])<<24 | long(ip_s[1])<<16 | long(ip_s[2])<<8 | \
long(ip_s[3])
# 10/8
if ip_l & (255<<24) == 10<<24:
return True
# 172.16/12
if ip_l & (255<<24 | 240<<16) == (172<<24 | 16<<16):
return True
# 192.168
if ip_l & (255<<24 | 255<<16) == (192<<24 | 168<<16):
return True
return False
my_ip = self.peerhost[0]
if not ip_is_local(my_ip):
self.connection.send(iq)
return
self.no_gupnp_reply_id = 0
def cleanup_gupnp():
if self.no_gupnp_reply_id:
gobject.source_remove(self.no_gupnp_reply_id)
self.no_gupnp_reply_id = 0
gajim.gupnp_igd.disconnect(self.ok_id)
gajim.gupnp_igd.disconnect(self.fail_id)
def ok(s, proto, ext_ip, re, ext_port, local_ip, local_port, desc):
log.debug('Got GUPnP-IGD answer: external: %s:%s, internal: %s:%s',
ext_ip, ext_port, local_ip, local_port)
if local_port != gajim.config.get('file_transfers_port'):
sender = file_props['sender']
receiver = file_props['receiver']
sha_str = helpers.get_auth_sha(file_props['sid'], sender,
receiver)
listener = gajim.socks5queue.start_listener(local_port, sha_str,
self._result_socks5_sid, file_props['sid'])
if listener:
self._add_streamhosts_to_query(query, sender, ext_port,
[ext_ip])
self.connection.send(iq)
cleanup_gupnp()
def fail(s, error, proto, ext_ip, local_ip, local_port, desc):
log.debug('Got GUPnP-IGD error : %s', str(error))
self.connection.send(iq)
cleanup_gupnp()
def no_upnp_reply():
log.debug('Got not GUPnP-IGD answer')
# stop trying to use it
gajim.HAVE_UPNP_IGD = False
self.no_gupnp_reply_id = 0
self.connection.send(iq)
cleanup_gupnp()
return False
self.ok_id = gajim.gupnp_igd.connect('mapped-external-port', ok)
self.fail_id = gajim.gupnp_igd.connect('error-mapping-port', fail)
port = gajim.config.get('file_transfers_port')
self.no_gupnp_reply_id = gobject.timeout_add_seconds(10, no_upnp_reply)
gajim.gupnp_igd.add_port('TCP', 0, my_ip, port, 3600,
'Gajim file transfer')
def _add_proxy_streamhosts_to_query(self, query, file_props):
proxyhosts = self._get_file_transfer_proxies_from_config(file_props)
if proxyhosts:

View File

@ -107,6 +107,10 @@ class FeaturesWindow:
_('Ability to start audio and video chat.'),
_('Requires python-farsight and gstreamer-plugins-bad.'),
_('Feature not available under Windows.')),
_('UPnP-IGD'): (self.gupnp_igd_available,
_('Ability to request your router to forward port for file transfer.'),
_('Requires python-gupnp-igd.'),
_('Feature not available under Windows.')),
}
# name, supported
@ -249,3 +253,6 @@ class FeaturesWindow:
def farsight_available(self):
return gajim.HAVE_FARSIGHT
def gupnp_igd_available(self):
return gajim.HAVE_UPNP_IGD