diff --git a/src/chat_control.py b/src/chat_control.py index 70a0f3fe0..a31af5cf4 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -53,7 +53,7 @@ from common.logger import constants from common.pep import MOODS, ACTIVITIES from common.xmpp.protocol import NS_XHTML, NS_XHTML_IM, NS_FILE, NS_MUC from common.xmpp.protocol import NS_RECEIPTS, NS_ESESSION -from common.xmpp.protocol import NS_JINGLE_RTP_AUDIO, NS_JINGLE_RTP_VIDEO, NS_JINGLE_ICE_UDP +from common.xmpp.protocol import NS_JINGLE_RTP_AUDIO, NS_JINGLE_RTP_VIDEO, NS_JINGLE_ICE_UDP, NS_JINGLE_FILE_TRANSFER from common.connection_handlers_events import MessageOutgoingEvent from command_system.implementation.middleware import ChatCommandProcessor diff --git a/src/common/connection_handlers_events.py b/src/common/connection_handlers_events.py index 63c7000ac..0b83de8bc 100644 --- a/src/common/connection_handlers_events.py +++ b/src/common/connection_handlers_events.py @@ -34,6 +34,7 @@ from common import exceptions from common.zeroconf import zeroconf from common.logger import LOG_DB_PATH from common.pep import SUPPORTED_PERSONAL_USER_EVENTS +from common.jingle_transport import JingleTransportSocks5 import gtkgui_helpers @@ -1818,6 +1819,10 @@ class FileRequestReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): name = 'file-request-received' base_network_events = [] + def init(self): + self.jingle_content = None + self.FT_content = None + def generate(self): self.get_id() self.fjid = self.conn._ft_get_from(self.stanza) @@ -1825,28 +1830,36 @@ class FileRequestReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): self.file_props = {'type': 'r'} self.file_props['sender'] = self.fjid self.file_props['request-id'] = self.id_ - si = self.stanza.getTag('si') - profile = si.getAttr('profile') - if profile != xmpp.NS_FILE: - self.conn.send_file_rejection(self.file_props, code='400', typ='profile') - raise xmpp.NodeProcessed - feature_tag = si.getTag('feature', namespace=xmpp.NS_FEATURE) - if not feature_tag: - return - form_tag = feature_tag.getTag('x', namespace=xmpp.NS_DATA) - if not form_tag: - return - self.dataform = dataforms.ExtendForm(node=form_tag) - for f in self.dataform.iter_fields(): - if f.var == 'stream-method' and f.type == 'list-single': - values = [o[1] for o in f.options] - self.file_props['stream-methods'] = ' '.join(values) - if xmpp.NS_BYTESTREAM in values or xmpp.NS_IBB in values: - break + if self.jingle_content: + self.file_props['session-type'] = 'jingle' + self.file_props['stream-methods'] = xmpp.NS_BYTESTREAM + file_tag = self.jingle_content.getTag('description').getTag( + 'offer').getTag('file') else: - self.conn.send_file_rejection(self.file_props, code='400', typ='stream') - raise xmpp.NodeProcessed - file_tag = si.getTag('file') + si = self.stanza.getTag('si') + profile = si.getAttr('profile') + if profile != xmpp.NS_FILE: + self.conn.send_file_rejection(self.file_props, code='400', + typ='profile') + raise xmpp.NodeProcessed + feature_tag = si.getTag('feature', namespace=xmpp.NS_FEATURE) + if not feature_tag: + return + form_tag = feature_tag.getTag('x', namespace=xmpp.NS_DATA) + if not form_tag: + return + self.dataform = dataforms.ExtendForm(node=form_tag) + for f in self.dataform.iter_fields(): + if f.var == 'stream-method' and f.type == 'list-single': + values = [o[1] for o in f.options] + self.file_props['stream-methods'] = ' '.join(values) + if xmpp.NS_BYTESTREAM in values or xmpp.NS_IBB in values: + break + else: + self.conn.send_file_rejection(self.file_props, code='400', + typ='stream') + raise xmpp.NodeProcessed + file_tag = si.getTag('file') for attribute in file_tag.getAttrs(): if attribute in ('name', 'size', 'hash', 'date'): val = file_tag.getAttr(attribute) @@ -1857,13 +1870,41 @@ class FileRequestReceivedEvent(nec.NetworkIncomingEvent, HelperEvent): if file_desc_tag is not None: self.file_props['desc'] = file_desc_tag.getData() - mime_type = si.getAttr('mime-type') - if mime_type is not None: - self.file_props['mime-type'] = mime_type + if not self.jingle_content: + mime_type = si.getAttr('mime-type') + if mime_type is not None: + self.file_props['mime-type'] = mime_type self.file_props['receiver'] = self.conn._ft_get_our_jid() - self.file_props['sid'] = unicode(si.getAttr('id')) self.file_props['transfered_size'] = [] + if self.jingle_content: + self.FT_content.use_security = bool(self.jingle_content.getTag( + 'security')) + self.file_props['session-sid'] = unicode(self.stanza.getTag( + 'jingle').getAttr('sid')) + + self.FT_content.file_props = self.file_props + if not self.FT_content.transport: + self.FT_content.transport = JingleTransportSocks5() + self.FT_content.transport.set_our_jid( + self.FT_content.session.ourjid) + self.FT_content.transport.set_connection( + self.FT_content.session.connection) + self.file_props['sid'] = self.FT_content.transport.sid + self.FT_content.session.connection.files_props[ + self.file_props['sid']] = self.file_props + self.FT_content.transport.set_file_props(self.file_props) + if self.file_props.has_key('streamhosts'): + self.file_props['streamhosts'].extend( + self.FT_content.transport.remote_candidates) + else: + self.file_props['streamhosts'] = \ + self.FT_content.transport.remote_candidates + for host in self.file_props['streamhosts']: + host['initiator'] = self.FT_content.session.initiator + host['target'] = self.FT_content.session.responder + else: + self.file_props['sid'] = unicode(si.getAttr('id')) return True class FileRequestErrorEvent(nec.NetworkIncomingEvent): diff --git a/src/common/jingle_ft.py b/src/common/jingle_ft.py index 697d24867..e385202c6 100644 --- a/src/common/jingle_ft.py +++ b/src/common/jingle_ft.py @@ -25,6 +25,7 @@ from jingle_content import contents, JingleContent from jingle_transport import JingleTransportICEUDP, JingleTransportSocks5 from common import helpers from common.socks5 import Socks5Receiver +from common.connection_handlers_events import FileRequestReceivedEvent import logging log = logging.getLogger('gajim.c.jingle_ft') @@ -87,55 +88,9 @@ class JingleFileTransfer(JingleContent): self.media = 'file' def __on_session_initiate(self, stanza, content, error, action): - jid = unicode(stanza.getFrom()) - log.info("jid:%s" % jid) - - file_props = {'type': 'r'} - file_props['sender'] = jid - file_props['request-id'] = unicode(stanza.getAttr('id')) - - file_props['session-type'] = 'jingle' - - self.use_security = bool(content.getTag('security')) - # TODO: extract fingerprint element, encryption method element for later - # use - - file_tag = content.getTag('description').getTag('offer').getTag('file') - for attribute in file_tag.getAttrs(): - if attribute in ('name', 'size', 'hash', 'date'): - val = file_tag.getAttr(attribute) - if val is None: - continue - file_props[attribute] = val - file_desc_tag = file_tag.getTag('desc') - if file_desc_tag is not None: - file_props['desc'] = file_desc_tag.getData() - - file_props['receiver'] = self.session.ourjid - log.info("ourjid: %s" % self.session.ourjid) - file_props['session-sid'] = unicode(stanza.getTag('jingle').getAttr('sid')) - 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_connection(self.session.connection) - self.file_props['sid'] = self.transport.sid - self.session.connection.files_props[file_props['sid']] = file_props - self.transport.set_file_props(self.file_props) - if self.file_props.has_key('streamhosts'): - self.file_props['streamhosts'].extend( - self.transport.remote_candidates) - else: - self.file_props['streamhosts'] = self.transport.remote_candidates - for host in self.file_props['streamhosts']: - host['initiator'] = self.session.initiator - host['target'] = self.session.responder - log.info("FT request: %s" % file_props) - - self.session.connection.dispatch('FILE_REQUEST', (jid, file_props)) + gajim.nec.push_incoming_event(FileRequestReceivedEvent(None, + conn=self.session.connection, stanza=stanza, jingle_content=content, + FT_content=self)) def __on_session_accept(self, stanza, content, error, action): log.info("__on_session_accept") diff --git a/src/common/jingle_xtls.py b/src/common/jingle_xtls.py index 2933a5193..edff95355 100644 --- a/src/common/jingle_xtls.py +++ b/src/common/jingle_xtls.py @@ -104,7 +104,8 @@ def get_context(fingerprint, verify_cb=None): store = ctx.get_cert_store() for f in os.listdir(os.path.expanduser(gajim.MY_PEER_CERTS_PATH)): load_cert_file(os.path.join(os.path.expanduser(gajim.MY_PEER_CERTS_PATH), f), store) - print 'certificate file' + f + ' loaded', 'fingerprint', fingerprint + log.debug('certificate file ' + f + ' loaded fingerprint ' + \ + fingerprint) return ctx def send_cert(con, jid_from, sid): diff --git a/src/common/socks5.py b/src/common/socks5.py index db2ef0b63..976c0d6ae 100644 --- a/src/common/socks5.py +++ b/src/common/socks5.py @@ -753,10 +753,11 @@ class Socks5Sender(Socks5, IdleObject): self.queue = parent Socks5.__init__(self, idlequeue, host, port, None, None, None) self._sock = _sock - if not self.fingerprint is None: + if self.fingerprint is not None: self._sock = OpenSSL.SSL.Connection( jingle_xtls.get_context('server'), self._sock) - self._sock.setblocking(False) + else: + self._sock.setblocking(False) self.fd = _sock.fileno() self._recv = _sock.recv self._send = _sock.send