JingleFT IBB fallback

This commit is contained in:
Jefry Lagrange 2011-06-28 18:31:07 -04:00
parent dc3b203168
commit a8fe25aaa4
5 changed files with 111 additions and 10 deletions

View File

@ -16,6 +16,7 @@ Handles Jingle contents (XEP 0166)
"""
import xmpp
from jingle_transport import JingleTransportIBB
contents = {}
@ -69,7 +70,7 @@ class JingleContent(object):
'session-initiate': [self.__on_transport_info],
'session-terminate': [],
'transport-info': [self.__on_transport_info],
'transport-replace': [],
'transport-replace': [self.__on_transport_replace],
'transport-accept': [],
'transport-reject': [],
'iq-result': [],
@ -109,6 +110,10 @@ class JingleContent(object):
for callback in self.callbacks[action]:
callback(stanza, content, error, action)
def __on_transport_replace(self, stanza, content, error, action):
content.addChild(node=self.transport.make_transport())
def __on_transport_info(self, stanza, content, error, action):
"""
Got a new transport candidate

View File

@ -23,6 +23,8 @@ import gajim
import xmpp
from jingle_content import contents, JingleContent
from jingle_transport import JingleTransportICEUDP, JingleTransportSocks5
from jingle_transport import JingleTransportIBB
from jingle_session import JingleStates
from common import helpers
from common.socks5 import Socks5Receiver
from common.connection_handlers_events import FileRequestReceivedEvent
@ -35,6 +37,7 @@ STATE_INITIALIZED = 1
STATE_ACCEPTED = 2
STATE_TRANSPORT_INFO = 3
STATE_PROXY_ACTIVATED = 4
STATE_TRANSPORT_REPLACE = 5
class JingleFileTransfer(JingleContent):
def __init__(self, session, transport=None, file_props=None,
@ -98,6 +101,19 @@ class JingleFileTransfer(JingleContent):
security = content.getTag('security')
if not security: # responder can not verify our fingerprint
self.use_security = False
if self.state == STATE_TRANSPORT_REPLACE:
# We ack the session accept
response = stanza.buildReply('result')
con = self.session.connection
con.connection.send(response)
# We send the file
con.files_props[self.file_props['sid']] = self.file_props
fp = open(self.file_props['file-name'], 'r')
con.OpenStream( self.transport.sid, self.session.peerjid,
fp, blocksize=4096)
raise xmpp.NodeProcessed
def __on_session_terminate(self, stanza, content, error, action):
log.info("__on_session_terminate")
@ -197,7 +213,7 @@ class JingleFileTransfer(JingleContent):
elif self.weinitiate and self.state == STATE_INITIALIZED:
# proxy activated
self.state = STATE_PROXY_ACTIVATED
def send_candidate_used(self, streamhost):
"""
send candidate-used stanza

View File

@ -28,8 +28,10 @@ Handles Jingle sessions (XEP 0166)
import gajim #Get rid of that?
import xmpp
from jingle_transport import get_jingle_transport
from jingle_transport import get_jingle_transport, JingleTransportIBB
from jingle_content import get_jingle_content, JingleContentSetupException
from jingle_content import JingleContent
from jingle_ft import STATE_TRANSPORT_REPLACE
from common.connection_handlers_events import *
import logging
log = logging.getLogger("gajim.c.jingle_session")
@ -213,11 +215,19 @@ class JingleSession(object):
if not self.contents:
self.end_session()
def modify_content(self, creator, name, *someother):
"""
We do not need this now
"""
pass
def modify_content(self, creator, name, transport = None):
'''
Currently used for transport replacement
'''
content = self.contents[(creator,name)]
transport.set_sid(content.transport.sid)
transport.set_file_props(content.transport.file_props)
content.transport = transport
# The content will have to be resend now that it is modified
content.sent = False
content.accepted = True
def on_session_state_changed(self, content=None):
if self.state == JingleStates.ended:
@ -343,18 +353,43 @@ class JingleSession(object):
error_name = child.getName()
self.__dispatch_error(error_name, text, error.getAttr('type'))
# FIXME: Not sure when we would want to do that...
def transport_replace(self):
transport = JingleTransportIBB()
# For debug only, delete this and replace for a function
# that will identify contents by its sid
for creator, name in self.contents.keys():
self.modify_content(creator, name, transport)
cont = self.contents[(creator, name)]
cont.transport = transport
cont.state = STATE_TRANSPORT_REPLACE
stanza, jingle = self.__make_jingle('transport-replace')
self.__append_contents(jingle)
self.__broadcast(stanza, jingle, None, 'transport-replace')
self.connection.connection.send(stanza)
#self.collect_iq_id(stanza.getID())
def __on_transport_replace(self, stanza, jingle, error, action):
for content in jingle.iterTags('content'):
creator = content['creator']
name = content['name']
if (creator, name) in self.contents:
transport_ns = content.getTag('transport').getNamespace()
if transport_ns == xmpp.JINGLE_ICE_UDP:
if transport_ns == xmpp.NS_JINGLE_ICE_UDP:
# FIXME: We don't manage anything else than ICE-UDP now...
# What was the previous transport?!?
# Anyway, content's transport is not modifiable yet
pass
elif transport_ns == xmpp.NS_JINGLE_IBB:
transport = JingleTransportIBB()
self.modify_content(creator, name, transport)
#self.state = JingleStates.pending
self.contents[(creator,name)].state = STATE_TRANSPORT_REPLACE
self.__ack(stanza, jingle, error, action)
self.__session_accept()
else:
stanza, jingle = self.__make_jingle('transport-reject')
content = jingle.setTag('content', attrs={'creator': creator,
@ -400,6 +435,7 @@ class JingleSession(object):
if self.state != JingleStates.pending:
raise OutOfOrder
self.state = JingleStates.active
def __on_content_accept(self, stanza, jingle, error, action):
"""
@ -562,12 +598,19 @@ class JingleSession(object):
return (contents, contents_rejected, failure_reason)
def __dispatch_error(self, error=None, text=None, type_=None):
if type_ == 'cancel' and error == 'item-not-found':
# We coudln't connect with sock5stream, we fallback to IBB
self.transport_replace()
return
if text:
text = '%s (%s)' % (error, text)
if type_ != 'modify':
gajim.nec.push_incoming_event(JingleErrorReceivedEvent(None,
conn=self.connection, jingle_session=self,
reason=text or error))
def __reason_from_stanza(self, stanza):
# TODO: Move to GUI?
@ -595,6 +638,8 @@ class JingleSession(object):
attrs['initiator'] = self.initiator
elif action == 'session-accept':
attrs['responder'] = self.responder
elif action == 'transport-replace':
attrs['initiator'] = self.initiator
jingle = stanza.addChild('jingle', attrs=attrs, namespace=xmpp.NS_JINGLE)
if reason is not None:
jingle.addChild(node=reason)

View File

@ -165,7 +165,7 @@ class JingleTransportSocks5(JingleTransport):
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['candidate_id'] = self.connection.connection.getAnID()
c['port'] = port
c['type'] = 'direct'
c['jid'] = self.ourjid
@ -272,6 +272,39 @@ class JingleTransportSocks5(JingleTransport):
return
sesn.send_transport_info(content)
class JingleTransportIBB(JingleTransport):
def __init__(self, node=None, block_sz=None):
JingleTransport.__init__(self, TransportType.streaming)
if block_sz:
self.block_sz = block_sz
else:
self.block_sz = '4096'
self.connection = None
self.sid = None
if node and node.getAttr('sid'):
self.sid = node.getAttr('sid')
def set_sid(self, sid):
self.sid = sid
def make_transport(self):
transport = JingleTransport.make_transport(self)
transport.setNamespace(xmpp.NS_JINGLE_IBB)
transport.setAttr('block-size', self.block_sz)
transport.setAttr('sid', self.sid)
return transport
def set_file_props(self, file_props):
self.file_props = file_props
import farsight
class JingleTransportICEUDP(JingleTransport):
@ -347,3 +380,4 @@ class JingleTransportICEUDP(JingleTransport):
transports[xmpp.NS_JINGLE_ICE_UDP] = JingleTransportICEUDP
transports[xmpp.NS_JINGLE_BYTESTREAM] = JingleTransportSocks5
transports[xmpp.NS_JINGLE_IBB] = JingleTransportIBB

View File

@ -91,6 +91,7 @@ NS_JINGLE_XTLS='urn:xmpp:jingle:security:xtls:0' # XTLS: EX
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_JINGLE_IBB = 'urn:xmpp:jingle:transports:ibb:1' # XEP-0261
NS_LAST = 'jabber:iq:last'
NS_LOCATION = 'http://jabber.org/protocol/geoloc' # XEP-0080
NS_MESSAGE = 'message' # Jabberd2