From b85e7849e8a8b57fff656a8f1dd7e653db22d430 Mon Sep 17 00:00:00 2001 From: Zhenchao Li Date: Sat, 19 Jun 2010 22:52:17 +0800 Subject: [PATCH] contruct transport candidates for jingle socks5 bytestream --- src/common/jingle_ft.py | 14 +++- src/common/jingle_session.py | 2 + src/common/jingle_transport.py | 119 ++++++++++++++++++++++++++++++ src/common/protocol/bytestream.py | 2 +- src/common/xmpp/protocol.py | 1 + 5 files changed, 134 insertions(+), 4 deletions(-) diff --git a/src/common/jingle_ft.py b/src/common/jingle_ft.py index 3bd50b989..7e609086f 100644 --- a/src/common/jingle_ft.py +++ b/src/common/jingle_ft.py @@ -22,7 +22,7 @@ Handles Jingle File Transfer (XEP 0234) import gajim import xmpp from jingle_content import contents, JingleContent -from jingle_transport import JingleTransportICEUDP +from jingle_transport import JingleTransportICEUDP, JingleTransportSocks5 import logging log = logging.getLogger('gajim.c.jingle_ft') @@ -32,6 +32,8 @@ class JingleFileTransfer(JingleContent): def __init__(self, session, transport=None, file_props=None): JingleContent.__init__(self, session, transport) + log.info("transport value: %s" % transport) + #events we might be interested in self.callbacks['session-initiate'] += [self.__on_session_initiate] self.callbacks['session-accept'] += [self.__on_session_accept] @@ -57,7 +59,10 @@ class JingleFileTransfer(JingleContent): if transport is None: - self.transport = JingleTransportICEUDP() + self.transport = JingleTransportSocks5() + self.transport.set_file_props(self.file_props) + self.transport.set_our_jid(session.ourjid) + log.info('ourjid: %s' % session.ourjid) self.session = session self.media = 'file' @@ -89,7 +94,10 @@ class JingleFileTransfer(JingleContent): file_props['transfered_size'] = [] self.file_props = file_props - + if self.transport is None: + self.transport = JingleTransportSocks5() + self.transport.set_our_jid(self.session.ourjid) + self.transport.set_file_props(self.file_props) log.info("FT request: %s" % file_props) #TODO diff --git a/src/common/jingle_session.py b/src/common/jingle_session.py index f2537a9f9..b2e9eb9c1 100644 --- a/src/common/jingle_session.py +++ b/src/common/jingle_session.py @@ -502,6 +502,8 @@ class JingleSession(object): for element in jingle.iterTags('content'): transport = get_jingle_transport(element.getTag('transport')) + if transport: + transport.ourjid = self.ourjid content_type = get_jingle_content(element.getTag('description')) if content_type: try: diff --git a/src/common/jingle_transport.py b/src/common/jingle_transport.py index 521564e87..312dcf121 100644 --- a/src/common/jingle_transport.py +++ b/src/common/jingle_transport.py @@ -16,6 +16,13 @@ Handles Jingle Transports (currently only ICE-UDP) """ import xmpp +import socket +from common import gajim +from common.protocol.bytestream import ConnectionSocks5Bytestream +import logging + +log = logging.getLogger('gajim.c.jingle_transport') + transports = {} @@ -71,6 +78,117 @@ class JingleTransport(object): """ return [] +class JingleTransportSocks5(JingleTransport): + """ + Socks5 transport in jingle scenario + Note: Don't forget to call set_file_props after initialization + """ + def __init__(self): + JingleTransport.__init__(self, TransportType.streaming) + + def set_file_props(self, file_props): + self.file_props = file_props + + def set_our_jid(self, jid): + self.ourjid = jid + + def make_candidate(self, candidate): + import logging + log = logging.getLogger() + log.info('candidate dict, %s' % candidate) + attrs = { + 'cid': candidate['candidate_id'], + 'host': candidate['host'], + 'jid': candidate['jid'], + 'port': candidate['port'], + 'priority': candidate['priority'], + 'type': candidate['type'] + } + + return xmpp.Node('candidate', attrs=attrs) + + def make_transport(self, candidates=None): + self._add_local_ips_as_candidates() + self._add_additional_candidates() + self._add_proxy_candidates() + transport = JingleTransport.make_transport(self, candidates) + transport.setNamespace(xmpp.NS_JINGLE_BYTESTREAM) + return transport + + def parse_transport_stanza(self, transport): + pass + + def _add_local_ips_as_candidates(self): + local_ip_cand = [] + port = gajim.config.get('file_transfers_port') + type_preference = 126 #type preference of connection type. XEP-0260 section 2.2 + jid_wo_resource = gajim.get_jid_without_resource(self.ourjid) + conn = gajim.connections[jid_wo_resource] + c = {'host': conn.peerhost[0]} + c['candidate_id'] = conn.connection.getAnID() + c['port'] = port + c['type'] = 'direct' + c['jid'] = self.ourjid + c['priority'] = (2**16) * type_preference + + local_ip_cand.append(c) + + for addr in socket.getaddrinfo(socket.gethostname(), None): + if not addr[4][0] in local_ip_cand and not addr[4][0].startswith('127'): + c = {'host': addr[4][0]} + c['candidate_id'] = conn.connection.getAnID() + c['port'] = port + c['type'] = 'direct' + c['jid'] = self.ourjid + c['priority'] = (2**16) * type_preference + local_ip_cand.append(c) + + self.candidates += local_ip_cand + + def _add_additional_candidates(self): + type_preference = 126 + additional_ip_cand = [] + port = gajim.config.get('file_transfers_port') + ft_add_hosts = gajim.config.get('ft_add_hosts_to_send') + jid_wo_resource = gajim.get_jid_without_resource(self.ourjid) + conn = gajim.connections[jid_wo_resource] + + if ft_add_hosts: + hosts = [e.strip() for e in ft_add_hosts.split(',')] + for h in hosts: + c = {'host': h} + c['candidate_id'] = conn.connection.getAnID() + c['port'] = port + c['type'] = 'direct' + c['jid'] = self.ourjid + c['priority'] = (2**16) * type_preference + additional_ip_cand.append(c) + self.candidates += additional_ip_cand + + def _add_proxy_candidates(self): + type_preference = 10 + proxy_cand = [] + socks5conn = ConnectionSocks5Bytestream() + socks5conn.name = self.ourjid + proxyhosts = socks5conn._get_file_transfer_proxies_from_config(self.file_props) + jid_wo_resource = gajim.get_jid_without_resource(self.ourjid) + conn = gajim.connections[jid_wo_resource] + + if proxyhosts: + file_props['proxy_receiver'] = unicode(file_props['receiver']) + file_props['proxy_sender'] = unicode(file_props['sender']) + file_props['proxyhosts'] = proxyhosts + + for proxyhost in proxyhosts: + c = {'host': proxyhost['host']} + c['candidate_id'] = conn.connection.getAnID() + c['port'] = proxyhost['port'] + c['type'] = 'proxy' + c['jid'] = self.ourjid + c['priority'] = (2**16) * type_preference + proxy_cand.append(c) + self.candidates += proxy_cand + import farsight @@ -146,3 +264,4 @@ class JingleTransportICEUDP(JingleTransport): return candidates transports[xmpp.NS_JINGLE_ICE_UDP] = JingleTransportICEUDP +transports[xmpp.NS_JINGLE_BYTESTREAM] = JingleTransportSocks5 diff --git a/src/common/protocol/bytestream.py b/src/common/protocol/bytestream.py index 7ed0764e1..32f4c170c 100644 --- a/src/common/protocol/bytestream.py +++ b/src/common/protocol/bytestream.py @@ -141,7 +141,7 @@ class ConnectionBytestream: if not session.accepted: session.approve_session() session.approve_content('file') - return + return iq = xmpp.Iq(to=unicode(file_props['sender']), typ='result') iq.setAttr('id', file_props['request-id']) diff --git a/src/common/xmpp/protocol.py b/src/common/xmpp/protocol.py index 0d1f15422..746bce722 100644 --- a/src/common/xmpp/protocol.py +++ b/src/common/xmpp/protocol.py @@ -72,6 +72,7 @@ NS_JINGLE_RTP_VIDEO='urn:xmpp:jingle:apps:rtp:video' # XEP-01 NS_JINGLE_FILE_TRANSFER='urn:xmpp:jingle:apps:file-transfer:1' # XEP-0234 NS_JINGLE_RAW_UDP='urn:xmpp:jingle:transports:raw-udp:1' # XEP-0177 NS_JINGLE_ICE_UDP='urn:xmpp:jingle:transports:ice-udp:1' # XEP-0176 +NS_JINGLE_BYTESTREAM ='urn:xmpp:jingle:transports:s5b:1' # XEP-0260 NS_LAST ='jabber:iq:last' NS_LOCATION ='http://jabber.org/protocol/geoloc' # XEP-0080 NS_MESSAGE ='message' # Jabberd2