Refactor IBB Handlers

- Move handling of Data IQs into IBBIqHandler
- Call SendHandler with file_props
- Save last sent id in file_props.syn_id
- Remove some useless checks, now that we call SendHandler with file_props
- Send item-not-found error on invalid session id
This commit is contained in:
Philipp Hörist 2017-03-30 03:33:51 +02:00
parent 385d6c3081
commit 7cb7bcaae6
1 changed files with 49 additions and 64 deletions

View File

@ -759,7 +759,6 @@ class ConnectionIBBytestream(ConnectionBytestream):
def __init__(self): def __init__(self):
ConnectionBytestream.__init__(self) ConnectionBytestream.__init__(self)
self._streams = {} self._streams = {}
self.last_sent_ibb_id = None
def IBBIqHandler(self, conn, stanza): def IBBIqHandler(self, conn, stanza):
""" """
@ -767,12 +766,22 @@ class ConnectionIBBytestream(ConnectionBytestream):
""" """
typ = stanza.getType() typ = stanza.getType()
log.debug('IBBIqHandler called typ->%s' % typ) log.debug('IBBIqHandler called typ->%s' % typ)
if typ == 'set' and stanza.getTag('open', namespace=nbxmpp.NS_IBB): if typ == 'set' and stanza.getTag('open'):
self.StreamOpenHandler(conn, stanza) self.StreamOpenHandler(conn, stanza)
elif typ == 'set' and stanza.getTag('close', namespace=nbxmpp.NS_IBB): elif typ == 'set' and stanza.getTag('close'):
self.StreamCloseHandler(conn, stanza) self.StreamCloseHandler(conn, stanza)
elif typ == 'result': elif typ == 'set' and stanza.getTag('data'):
self.SendHandler() sid = stanza.getTagAttr('data', 'sid')
file_props = FilesProp.getFilePropByTransportSid(self.name, sid)
if not file_props:
conn.send(nbxmpp.Error(stanza, nbxmpp.ERR_ITEM_NOT_FOUND))
elif file_props.connected and self.IBBMessageHandler(conn,
stanza):
reply = stanza.buildReply('result')
reply.delChild('data')
conn.send(reply)
elif not file_props.connected:
log.debug('Received IQ for closed filetransfer, IQ dropped')
elif typ == 'error': elif typ == 'error':
gajim.socks5queue.error_cb() gajim.socks5queue.error_cb()
else: else:
@ -849,7 +858,7 @@ class ConnectionIBBytestream(ConnectionBytestream):
base64 encoding that increases size of data by 1/3. base64 encoding that increases size of data by 1/3.
""" """
file_props = FilesProp.getFilePropBySid(sid) file_props = FilesProp.getFilePropBySid(sid)
file_props.direction = '|>' file_props.direction = '>'
file_props.block_size = blocksize file_props.block_size = blocksize
file_props.fp = fp file_props.fp = fp
file_props.seq = 0 file_props.seq = 0
@ -868,50 +877,41 @@ class ConnectionIBBytestream(ConnectionBytestream):
file_props.syn_id = syn.getID() file_props.syn_id = syn.getID()
return file_props return file_props
def SendHandler(self): def SendHandler(self, file_props):
""" """
Send next portion of data if it is time to do it. Used internally. Send next portion of data if it is time to do it. Used internally.
""" """
log.debug('SendHandler called') log.debug('SendHandler called')
for file_props in FilesProp.getAllFileProp(): if file_props.completed:
if not file_props.direction: self.CloseIBBStream(file_props)
# it's socks5 bytestream if file_props.paused:
continue return
if file_props.completed: if not file_props.connected:
self.CloseIBBStream(file_props) #TODO: Reply with out of order error
sid = file_props.sid return
if file_props.direction[:2] == '|>': chunk = file_props.fp.read(file_props.block_size)
# We waitthat other part accept stream if chunk:
continue datanode = nbxmpp.Node(nbxmpp.NS_IBB + ' data', {
if file_props.direction[0] == '>': 'sid': file_props.transport_sid,
if file_props.paused: 'seq': file_props.seq},
continue base64.b64encode(chunk).decode('ascii'))
if not file_props.connected: file_props.seq += 1
#TODO: Reply with out of order error file_props.started = True
continue if file_props.seq == 65536:
chunk = file_props.fp.read(file_props.block_size) file_props.seq = 0
if chunk: file_props.syn_id = self.connection.send(
datanode = nbxmpp.Node(nbxmpp.NS_IBB + ' data', { nbxmpp.Protocol(name='iq', to=file_props.receiver,
'sid': file_props.transport_sid, typ='set', payload=[datanode]))
'seq': file_props.seq}, base64.b64encode(chunk.encode( current_time = time.time()
'utf-8')).decode('utf-8')) file_props.elapsed_time += current_time - file_props.last_time
file_props.seq += 1 file_props.last_time = current_time
file_props.started = True file_props.received_len += len(chunk)
if file_props.seq == 65536: if file_props.size == file_props.received_len:
file_props.seq = 0 file_props.completed = True
self.last_sent_ibb_id = self.connection.send( gajim.socks5queue.progress_transfer_cb(self.name,
nbxmpp.Protocol(name='iq', to=file_props.receiver, file_props)
typ='set', payload=[datanode])) else:
current_time = time.time() log.debug('Nothing to read, but file not completed')
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
gajim.socks5queue.progress_transfer_cb(self.name,
file_props)
else:
log.debug('Nothing to read, but file not completed')
def IBBMessageHandler(self, conn, stanza): def IBBMessageHandler(self, conn, stanza):
""" """
@ -980,6 +980,7 @@ class ConnectionIBBytestream(ConnectionBytestream):
else: else:
conn.send(nbxmpp.Error(stanza, nbxmpp.ERR_ITEM_NOT_FOUND)) conn.send(nbxmpp.Error(stanza, nbxmpp.ERR_ITEM_NOT_FOUND))
def IBBAllIqHandler(self, conn, stanza): def IBBAllIqHandler(self, conn, stanza):
""" """
Handle remote side reply about if it agree or not to receive our Handle remote side reply about if it agree or not to receive our
@ -1001,25 +1002,9 @@ class ConnectionIBBytestream(ConnectionBytestream):
else: else:
conn.Event('IBB', 'ERROR ON SEND', file_props) conn.Event('IBB', 'ERROR ON SEND', file_props)
elif stanza.getType() == 'result': elif stanza.getType() == 'result':
if file_props.direction[0] == '|': self.SendHandler(file_props)
file_props.direction = file_props.direction[1:]
self.SendHandler()
else:
conn.send(nbxmpp.Error(stanza,
nbxmpp.ERR_UNEXPECTED_REQUEST))
break break
else:
if stanza.getTag('data'):
sid = stanza.getTagAttr('data', 'sid')
file_props = FilesProp.getFilePropByTransportSid(self.name, sid)
if file_props.connected and self.IBBMessageHandler(conn,
stanza):
reply = stanza.buildReply('result')
reply.delChild('data')
conn.send(reply)
raise nbxmpp.NodeProcessed
elif syn_id == self.last_sent_ibb_id:
self.SendHandler()
class ConnectionSocks5BytestreamZeroconf(ConnectionSocks5Bytestream): class ConnectionSocks5BytestreamZeroconf(ConnectionSocks5Bytestream):