Commit fdfc9c90 authored by Philipp Hörist's avatar Philipp Hörist

Move IBB code to new IBB module

parent 7ec93f89
......@@ -34,7 +34,6 @@ from gajim.common import helpers
from gajim.common import jingle_xtls
from gajim.common.jingle import ConnectionJingle
from gajim.common.protocol.bytestream import ConnectionSocks5Bytestream
from gajim.common.protocol.bytestream import ConnectionIBBytestream
from gajim.common.connection_handlers_events import StreamReceivedEvent
from gajim.common.connection_handlers_events import PresenceReceivedEvent
from gajim.common.connection_handlers_events import StreamConflictReceivedEvent
......@@ -185,10 +184,9 @@ class ConnectionHandlersBase:
class ConnectionHandlers(ConnectionSocks5Bytestream,
ConnectionHandlersBase,
ConnectionJingle, ConnectionIBBytestream):
ConnectionJingle):
def __init__(self):
ConnectionSocks5Bytestream.__init__(self)
ConnectionIBBytestream.__init__(self)
ConnectionJingle.__init__(self)
ConnectionHandlersBase.__init__(self)
......@@ -223,10 +221,6 @@ class ConnectionHandlers(ConnectionSocks5Bytestream,
nbxmpp.NS_BYTESTREAM)
con.RegisterHandler('iq', self._bytestreamErrorCB, 'error',
nbxmpp.NS_BYTESTREAM)
con.RegisterHandlerOnce('iq', self.IBBAllIqHandler)
con.RegisterHandler('iq', self.IBBIqHandler, ns=nbxmpp.NS_IBB)
con.RegisterHandler('message', self.IBBMessageHandler, ns=nbxmpp.NS_IBB)
con.RegisterHandler('iq', self._JingleCB, 'result')
con.RegisterHandler('iq', self._JingleCB, 'error')
con.RegisterHandler('iq', self._JingleCB, 'set', nbxmpp.NS_JINGLE)
......
......@@ -146,8 +146,9 @@ class StateTransfering(JingleFileTransferStates):
def _start_ibb_transfer(self, con):
self.jft.file_props.transport_sid = self.jft.transport.sid
fp = open(self.jft.file_props.file_name, 'rb')
con.OpenStream(self.jft.file_props.sid, self.jft.session.peerjid, fp,
blocksize=4096)
con.get_module('IBB').send_open(self.jft.session.peerjid,
self.jft.file_props.sid,
fp)
def _start_sock5_transfer(self):
# It tells wether we start the transfer as client or server
......
......@@ -74,6 +74,7 @@ MODULES = [
'vcard_avatars',
'vcard_temp',
'announce',
'ibb',
]
_imported_modules = [] # type: List[tuple]
......
# This file is part of Gajim.
#
# Gajim 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 3 only.
#
# Gajim 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.
#
# You should have received a copy of the GNU General Public License
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
# XEP-0047: In-Band Bytestreams
import time
import nbxmpp
from nbxmpp.protocol import NodeProcessed
from nbxmpp.structs import StanzaHandler
from nbxmpp.util import is_error_result
from gajim.common import app
from gajim.common.modules.base import BaseModule
from gajim.common.file_props import FilesProp
class IBB(BaseModule):
_nbxmpp_extends = 'IBB'
_nbxmpp_methods = [
'send_open',
'send_close',
'send_data',
'send_reply',
]
def __init__(self, con):
BaseModule.__init__(self, con)
self.handlers = [
StanzaHandler(name='iq',
callback=self._ibb_received,
ns=nbxmpp.NS_IBB),
]
def _ibb_received(self, _con, stanza, properties):
if not properties.is_ibb:
return
if properties.ibb.type == 'data':
self._log.info('Data received, sid: %s, seq: %s',
properties.ibb.sid, properties.ibb.seq)
file_props = FilesProp.getFilePropByTransportSid(self._account,
properties.ibb.sid)
if not file_props:
self.send_reply(stanza, nbxmpp.ERR_ITEM_NOT_FOUND)
raise NodeProcessed
if file_props.connected:
self._on_data_received(stanza, file_props, properties)
self.send_reply(stanza)
elif properties.ibb.type == 'open':
self._log.info('Open received, sid: %s, blocksize: %s',
properties.ibb.sid, properties.ibb.block_size)
file_props = FilesProp.getFilePropByTransportSid(self._account,
properties.ibb.sid)
if not file_props:
self.send_reply(stanza, nbxmpp.ERR_ITEM_NOT_FOUND)
raise NodeProcessed
file_props.block_size = properties.ibb.block_size
file_props.direction = '<'
file_props.seq = 0
file_props.received_len = 0
file_props.last_time = time.time()
file_props.error = 0
file_props.paused = False
file_props.connected = True
file_props.completed = False
file_props.disconnect_cb = None
file_props.continue_cb = None
file_props.syn_id = stanza.getID()
file_props.fp = open(file_props.file_name, 'wb')
self.send_reply(stanza)
elif properties.ibb.type == 'close':
self._log.info('Close received, sid: %s', properties.ibb.sid)
file_props = FilesProp.getFilePropByTransportSid(self._account,
properties.ibb.sid)
if not file_props:
self.send_reply(stanza, nbxmpp.ERR_ITEM_NOT_FOUND)
raise NodeProcessed
self.send_reply(stanza)
file_props.fp.close()
file_props.completed = file_props.received_len >= file_props.size
if not file_props.completed:
file_props.error = -1
app.socks5queue.complete_transfer_cb(self._account, file_props)
raise NodeProcessed
def _on_data_received(self, stanza, file_props, properties):
ibb = properties.ibb
if ibb.seq != file_props.seq:
self.send_reply(stanza, nbxmpp.ERR_UNEXPECTED_REQUEST)
self.send_close(file_props)
raise NodeProcessed
self._log.debug('Data received: sid: %s, %s+%s bytes',
ibb.sid, file_props.fp.tell(), len(ibb.data))
file_props.seq += 1
file_props.started = True
file_props.fp.write(ibb.data)
current_time = time.time()
file_props.elapsed_time += current_time - file_props.last_time
file_props.last_time = current_time
file_props.received_len += len(ibb.data)
app.socks5queue.progress_transfer_cb(self._account, file_props)
if file_props.received_len >= file_props.size:
file_props.completed = True
def send_open(self, to, sid, fp):
self._log.info('Send open to %s, sid: %s', to, sid)
file_props = FilesProp.getFilePropBySid(sid)
file_props.direction = '>'
file_props.block_size = 4096
file_props.fp = fp
file_props.seq = -1
file_props.error = 0
file_props.paused = False
file_props.received_len = 0
file_props.last_time = time.time()
file_props.connected = True
file_props.completed = False
file_props.disconnect_cb = None
file_props.continue_cb = None
self._nbxmpp('IBB').send_open(to,
file_props.transport_sid,
4096,
callback=self._on_open_result,
user_data=file_props)
return file_props
def _on_open_result(self, result, file_props):
if is_error_result(result):
app.socks5queue.error_cb('Error', str(result))
self._log.warning('Error: %s', result)
return
self.send_data(file_props)
def send_close(self, file_props):
file_props.connected = False
file_props.fp.close()
file_props.stopped = True
to = file_props.receiver
if file_props.direction == '<':
to = file_props.sender
self._log.info('Send close to %s, sid: %s',
to, file_props.transport_sid)
self._nbxmpp('IBB').send_close(to, file_props.transport_sid,
callback=self._on_close_result)
if file_props.completed:
app.socks5queue.complete_transfer_cb(self._account, file_props)
else:
if file_props.type_ == 's':
peerjid = file_props.receiver
else:
peerjid = file_props.sender
session = self._con.get_jingle_session(
peerjid, file_props.sid, 'file')
# According to the xep, the initiator also cancels
# the jingle session if there are no more files to send using IBB
if session.weinitiate:
session.cancel_session()
def _on_close_result(self, result):
if is_error_result(result):
app.socks5queue.error_cb('Error', str(result))
self._log.warning('Error: %s', result)
return
def send_data(self, file_props):
if file_props.completed:
self.send_close(file_props)
return
chunk = file_props.fp.read(file_props.block_size)
if chunk:
file_props.seq += 1
file_props.started = True
if file_props.seq == 65536:
file_props.seq = 0
self._log.info('Send data to %s, sid: %s',
file_props.receiver, file_props.transport_sid)
self._nbxmpp('IBB').send_data(file_props.receiver,
file_props.transport_sid,
file_props.seq,
chunk,
callback=self._on_data_result,
user_data=file_props)
current_time = time.time()
file_props.elapsed_time += current_time - file_props.last_time
file_props.last_time = current_time
file_props.received_len += len(chunk)
if file_props.size == file_props.received_len:
file_props.completed = True
app.socks5queue.progress_transfer_cb(self._account, file_props)
def _on_data_result(self, result, file_props):
if is_error_result(result):
app.socks5queue.error_cb('Error', str(result))
self._log.warning('Error: %s', result)
return
self.send_data(file_props)
def get_instance(*args, **kwargs):
return IBB(*args, **kwargs), 'IBB'
This diff is collapsed.
......@@ -882,7 +882,7 @@ class FileTransfersWindow:
con = app.connections[account]
# Check if we are in a IBB transfer
if file_props.direction:
con.CloseIBBStream(file_props)
con.get_module('IBB').send_close(file_props)
con.disconnect_transfer(file_props)
self.set_status(file_props, 'stop')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment