2009-11-15 20:47:06 +01:00
|
|
|
##
|
|
|
|
## Copyright (C) 2006 Gajim Team
|
|
|
|
##
|
|
|
|
## This program is free software; you can redistribute it and/or modify
|
|
|
|
## it under the terms of the GNU General Public License as published
|
|
|
|
## by the Free Software Foundation; version 2 only.
|
|
|
|
##
|
|
|
|
## This program is distributed in the hope that it will be useful,
|
|
|
|
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
## GNU General Public License for more details.
|
|
|
|
##
|
2009-11-26 12:58:12 +01:00
|
|
|
|
|
|
|
"""
|
|
|
|
Handles Jingle Transports (currently only ICE-UDP)
|
|
|
|
"""
|
2009-11-15 20:47:06 +01:00
|
|
|
|
|
|
|
import xmpp
|
|
|
|
|
|
|
|
transports = {}
|
|
|
|
|
|
|
|
def get_jingle_transport(node):
|
2010-02-08 15:08:40 +01:00
|
|
|
namespace = node.getNamespace()
|
|
|
|
if namespace in transports:
|
|
|
|
return transports[namespace]()
|
2009-11-15 20:47:06 +01:00
|
|
|
|
|
|
|
|
|
|
|
class TransportType(object):
|
2010-02-08 15:08:40 +01:00
|
|
|
"""
|
|
|
|
Possible types of a JingleTransport
|
|
|
|
"""
|
|
|
|
datagram = 1
|
|
|
|
streaming = 2
|
2009-11-15 20:47:06 +01:00
|
|
|
|
|
|
|
|
|
|
|
class JingleTransport(object):
|
2010-02-08 15:08:40 +01:00
|
|
|
"""
|
|
|
|
An abstraction of a transport in Jingle sessions
|
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__(self, type_):
|
|
|
|
self.type = type_
|
|
|
|
self.candidates = []
|
|
|
|
self.remote_candidates = []
|
|
|
|
|
|
|
|
def _iter_candidates(self):
|
|
|
|
for candidate in self.candidates:
|
|
|
|
yield self.make_candidate(candidate)
|
|
|
|
|
|
|
|
def make_candidate(self, candidate):
|
|
|
|
"""
|
|
|
|
Build a candidate stanza for the given candidate
|
|
|
|
"""
|
|
|
|
pass
|
|
|
|
|
|
|
|
def make_transport(self, candidates=None):
|
|
|
|
"""
|
|
|
|
Build a transport stanza with the given candidates (or self.candidates if
|
|
|
|
candidates is None)
|
|
|
|
"""
|
|
|
|
if not candidates:
|
|
|
|
candidates = self._iter_candidates()
|
|
|
|
else:
|
|
|
|
candidates = (self.make_candidate(candidate) for candidate in candidates)
|
|
|
|
transport = xmpp.Node('transport', payload=candidates)
|
|
|
|
return transport
|
|
|
|
|
|
|
|
def parse_transport_stanza(self, transport):
|
|
|
|
"""
|
|
|
|
Return the list of transport candidates from a transport stanza
|
|
|
|
"""
|
|
|
|
return []
|
2009-11-15 21:21:10 +01:00
|
|
|
|
2009-11-15 20:47:06 +01:00
|
|
|
|
|
|
|
import farsight
|
|
|
|
|
|
|
|
class JingleTransportICEUDP(JingleTransport):
|
2010-02-08 15:08:40 +01:00
|
|
|
def __init__(self):
|
|
|
|
JingleTransport.__init__(self, TransportType.datagram)
|
|
|
|
|
|
|
|
def make_candidate(self, candidate):
|
|
|
|
types = {farsight.CANDIDATE_TYPE_HOST: 'host',
|
|
|
|
farsight.CANDIDATE_TYPE_SRFLX: 'srflx',
|
|
|
|
farsight.CANDIDATE_TYPE_PRFLX: 'prflx',
|
|
|
|
farsight.CANDIDATE_TYPE_RELAY: 'relay',
|
|
|
|
farsight.CANDIDATE_TYPE_MULTICAST: 'multicast'}
|
|
|
|
attrs = {
|
|
|
|
'component': candidate.component_id,
|
|
|
|
'foundation': '1', # hack
|
|
|
|
'generation': '0',
|
|
|
|
'ip': candidate.ip,
|
|
|
|
'network': '0',
|
|
|
|
'port': candidate.port,
|
|
|
|
'priority': int(candidate.priority), # hack
|
|
|
|
}
|
|
|
|
if candidate.type in types:
|
|
|
|
attrs['type'] = types[candidate.type]
|
|
|
|
if candidate.proto == farsight.NETWORK_PROTOCOL_UDP:
|
|
|
|
attrs['protocol'] = 'udp'
|
|
|
|
else:
|
|
|
|
# we actually don't handle properly different tcp options in jingle
|
|
|
|
attrs['protocol'] = 'tcp'
|
|
|
|
return xmpp.Node('candidate', attrs=attrs)
|
|
|
|
|
|
|
|
def make_transport(self, candidates=None):
|
|
|
|
transport = JingleTransport.make_transport(self, candidates)
|
|
|
|
transport.setNamespace(xmpp.NS_JINGLE_ICE_UDP)
|
|
|
|
if self.candidates and self.candidates[0].username and \
|
|
|
|
self.candidates[0].password:
|
|
|
|
transport.setAttr('ufrag', self.candidates[0].username)
|
|
|
|
transport.setAttr('pwd', self.candidates[0].password)
|
|
|
|
return transport
|
|
|
|
|
|
|
|
def parse_transport_stanza(self, transport):
|
|
|
|
candidates = []
|
|
|
|
for candidate in transport.iterTags('candidate'):
|
|
|
|
cand = farsight.Candidate()
|
|
|
|
cand.component_id = int(candidate['component'])
|
|
|
|
cand.ip = str(candidate['ip'])
|
|
|
|
cand.port = int(candidate['port'])
|
|
|
|
cand.foundation = str(candidate['foundation'])
|
|
|
|
#cand.type = farsight.CANDIDATE_TYPE_LOCAL
|
|
|
|
cand.priority = int(candidate['priority'])
|
|
|
|
|
|
|
|
if candidate['protocol'] == 'udp':
|
|
|
|
cand.proto = farsight.NETWORK_PROTOCOL_UDP
|
|
|
|
else:
|
|
|
|
# we actually don't handle properly different tcp options in jingle
|
|
|
|
cand.proto = farsight.NETWORK_PROTOCOL_TCP
|
|
|
|
|
|
|
|
cand.username = str(transport['ufrag'])
|
|
|
|
cand.password = str(transport['pwd'])
|
|
|
|
|
|
|
|
#FIXME: huh?
|
|
|
|
types = {'host': farsight.CANDIDATE_TYPE_HOST,
|
|
|
|
'srflx': farsight.CANDIDATE_TYPE_SRFLX,
|
|
|
|
'prflx': farsight.CANDIDATE_TYPE_PRFLX,
|
|
|
|
'relay': farsight.CANDIDATE_TYPE_RELAY,
|
|
|
|
'multicast': farsight.CANDIDATE_TYPE_MULTICAST}
|
|
|
|
if 'type' in candidate and candidate['type'] in types:
|
|
|
|
cand.type = types[candidate['type']]
|
|
|
|
else:
|
|
|
|
print 'Unknown type %s', candidate['type']
|
|
|
|
candidates.append(cand)
|
|
|
|
self.remote_candidates.extend(candidates)
|
|
|
|
return candidates
|
2009-11-15 20:47:06 +01:00
|
|
|
|
|
|
|
transports[xmpp.NS_JINGLE_ICE_UDP] = JingleTransportICEUDP
|