Package common :: Package protocol :: Module bytestream
[hide private]
[frames] | no frames]

Source Code for Module common.protocol.bytestream

  1  # -*- coding:utf-8 -*- 
  2  ## src/common/connection_handlers.py 
  3  ## 
  4  ## Copyright (C) 2006 Dimitur Kirov <dkirov AT gmail.com> 
  5  ##                    Junglecow J <junglecow AT gmail.com> 
  6  ## Copyright (C) 2006-2007 Tomasz Melcer <liori AT exroot.org> 
  7  ##                         Travis Shirk <travis AT pobox.com> 
  8  ##                         Nikos Kouremenos <kourem AT gmail.com> 
  9  ## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org> 
 10  ## Copyright (C) 2007 Julien Pivotto <roidelapluie AT gmail.com> 
 11  ## Copyright (C) 2007-2008 Brendan Taylor <whateley AT gmail.com> 
 12  ##                         Jean-Marie Traissard <jim AT lapin.org> 
 13  ##                         Stephan Erb <steve-e AT h3c.de> 
 14  ## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org> 
 15  ## 
 16  ## This file is part of Gajim. 
 17  ## 
 18  ## Gajim is free software; you can redistribute it and/or modify 
 19  ## it under the terms of the GNU General Public License as published 
 20  ## by the Free Software Foundation; version 3 only. 
 21  ## 
 22  ## Gajim is distributed in the hope that it will be useful, 
 23  ## but WITHOUT ANY WARRANTY; without even the implied warranty of 
 24  ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 25  ## GNU General Public License for more details. 
 26  ## 
 27  ## You should have received a copy of the GNU General Public License 
 28  ## along with Gajim. If not, see <http://www.gnu.org/licenses/>. 
 29  ## 
 30   
 31  import socket 
 32   
 33  from common import xmpp 
 34  from common import gajim 
 35  from common import helpers 
 36  from common import dataforms 
 37   
 38  from common.socks5 import Socks5Receiver 
 39   
 40   
41 -def is_transfer_paused(file_props):
42 if 'stopped' in file_props and file_props['stopped']: 43 return False 44 if 'completed' in file_props and file_props['completed']: 45 return False 46 if 'disconnect_cb' not in file_props: 47 return False 48 return file_props['paused']
49
50 -def is_transfer_active(file_props):
51 if 'stopped' in file_props and file_props['stopped']: 52 return False 53 if 'completed' in file_props and file_props['completed']: 54 return False 55 if 'started' not in file_props or not file_props['started']: 56 return False 57 if 'paused' not in file_props: 58 return True 59 return not file_props['paused']
60
61 -def is_transfer_stopped(file_props):
62 if 'error' in file_props and file_props['error'] != 0: 63 return True 64 if 'completed' in file_props and file_props['completed']: 65 return True 66 if 'connected' in file_props and file_props['connected'] == False: 67 return True 68 if 'stopped' not in file_props or not file_props['stopped']: 69 return False 70 return True
71 72
73 -class ConnectionBytestream:
74
75 - def __init__(self):
76 self.files_props = {}
77
78 - def _ft_get_our_jid(self):
79 our_jid = gajim.get_jid_from_account(self.name) 80 resource = self.server_resource 81 return our_jid + '/' + resource
82
83 - def _ft_get_receiver_jid(self, file_props):
84 return file_props['receiver'].jid + '/' + file_props['receiver'].resource
85
86 - def _ft_get_from(self, iq_obj):
87 return helpers.get_full_jid_from_iq(iq_obj)
88
89 - def _ft_get_streamhost_jid_attr(self, streamhost):
90 return helpers.parse_jid(streamhost.getAttr('jid'))
91
92 - def send_file_request(self, file_props):
93 """ 94 Send iq for new FT request 95 """ 96 if not self.connection or self.connected < 2: 97 return 98 file_props['sender'] = self._ft_get_our_jid() 99 fjid = self._ft_get_receiver_jid(file_props) 100 iq = xmpp.Iq(to=fjid, typ='set') 101 iq.setID(file_props['sid']) 102 self.files_props[file_props['sid']] = file_props 103 si = iq.setTag('si', namespace=xmpp.NS_SI) 104 si.setAttr('profile', xmpp.NS_FILE) 105 si.setAttr('id', file_props['sid']) 106 file_tag = si.setTag('file', namespace=xmpp.NS_FILE) 107 file_tag.setAttr('name', file_props['name']) 108 file_tag.setAttr('size', file_props['size']) 109 desc = file_tag.setTag('desc') 110 if 'desc' in file_props: 111 desc.setData(file_props['desc']) 112 file_tag.setTag('range') 113 feature = si.setTag('feature', namespace=xmpp.NS_FEATURE) 114 _feature = xmpp.DataForm(typ='form') 115 feature.addChild(node=_feature) 116 field = _feature.setField('stream-method') 117 field.setAttr('type', 'list-single') 118 field.addOption(xmpp.NS_BYTESTREAM) 119 self.connection.send(iq)
120
121 - def send_file_approval(self, file_props):
122 """ 123 Send iq, confirming that we want to download the file 124 """ 125 # user response to ConfirmationDialog may come after we've disconneted 126 if not self.connection or self.connected < 2: 127 return 128 iq = xmpp.Iq(to=unicode(file_props['sender']), typ='result') 129 iq.setAttr('id', file_props['request-id']) 130 si = iq.setTag('si', namespace=xmpp.NS_SI) 131 if 'offset' in file_props and file_props['offset']: 132 file_tag = si.setTag('file', namespace=xmpp.NS_FILE) 133 range_tag = file_tag.setTag('range') 134 range_tag.setAttr('offset', file_props['offset']) 135 feature = si.setTag('feature', namespace=xmpp.NS_FEATURE) 136 _feature = xmpp.DataForm(typ='submit') 137 feature.addChild(node=_feature) 138 field = _feature.setField('stream-method') 139 field.delAttr('type') 140 field.setValue(xmpp.NS_BYTESTREAM) 141 self.connection.send(iq)
142
143 - def send_file_rejection(self, file_props, code='403', typ=None):
144 """ 145 Inform sender that we refuse to download the file 146 147 typ is used when code = '400', in this case typ can be 'strean' for 148 invalid stream or 'profile' for invalid profile 149 """ 150 # user response to ConfirmationDialog may come after we've disconneted 151 if not self.connection or self.connected < 2: 152 return 153 iq = xmpp.Iq(to=unicode(file_props['sender']), typ='error') 154 iq.setAttr('id', file_props['request-id']) 155 if code == '400' and typ in ('stream', 'profile'): 156 name = 'bad-request' 157 text = '' 158 else: 159 name = 'forbidden' 160 text = 'Offer Declined' 161 err = xmpp.ErrorNode(code=code, typ='cancel', name=name, text=text) 162 if code == '400' and typ in ('stream', 'profile'): 163 if typ == 'stream': 164 err.setTag('no-valid-streams', namespace=xmpp.NS_SI) 165 else: 166 err.setTag('bad-profile', namespace=xmpp.NS_SI) 167 iq.addChild(node=err) 168 self.connection.send(iq)
169
170 - def _siResultCB(self, con, iq_obj):
171 file_props = self.files_props.get(iq_obj.getAttr('id')) 172 if not file_props: 173 return 174 if 'request-id' in file_props: 175 # we have already sent streamhosts info 176 return 177 file_props['receiver'] = self._ft_get_from(iq_obj) 178 si = iq_obj.getTag('si') 179 file_tag = si.getTag('file') 180 range_tag = None 181 if file_tag: 182 range_tag = file_tag.getTag('range') 183 if range_tag: 184 offset = range_tag.getAttr('offset') 185 if offset: 186 file_props['offset'] = int(offset) 187 length = range_tag.getAttr('length') 188 if length: 189 file_props['length'] = int(length) 190 feature = si.setTag('feature') 191 if feature.getNamespace() != xmpp.NS_FEATURE: 192 return 193 form_tag = feature.getTag('x') 194 form = xmpp.DataForm(node=form_tag) 195 field = form.getField('stream-method') 196 if field.getValue() != xmpp.NS_BYTESTREAM: 197 return 198 self._send_socks5_info(file_props) 199 raise xmpp.NodeProcessed
200
201 - def _siSetCB(self, con, iq_obj):
202 jid = self._ft_get_from(iq_obj) 203 file_props = {'type': 'r'} 204 file_props['sender'] = jid 205 file_props['request-id'] = unicode(iq_obj.getAttr('id')) 206 si = iq_obj.getTag('si') 207 profile = si.getAttr('profile') 208 mime_type = si.getAttr('mime-type') 209 if profile != xmpp.NS_FILE: 210 self.send_file_rejection(file_props, code='400', typ='profile') 211 raise xmpp.NodeProcessed 212 feature_tag = si.getTag('feature', namespace=xmpp.NS_FEATURE) 213 if not feature_tag: 214 return 215 form_tag = feature_tag.getTag('x', namespace=xmpp.NS_DATA) 216 if not form_tag: 217 return 218 form = dataforms.ExtendForm(node=form_tag) 219 for f in form.iter_fields(): 220 if f.var == 'stream-method' and f.type == 'list-single': 221 values = [o[1] for o in f.options] 222 if xmpp.NS_BYTESTREAM in values: 223 break 224 else: 225 self.send_file_rejection(file_props, code='400', typ='stream') 226 raise xmpp.NodeProcessed 227 file_tag = si.getTag('file') 228 for attribute in file_tag.getAttrs(): 229 if attribute in ('name', 'size', 'hash', 'date'): 230 val = file_tag.getAttr(attribute) 231 if val is None: 232 continue 233 file_props[attribute] = val 234 file_desc_tag = file_tag.getTag('desc') 235 if file_desc_tag is not None: 236 file_props['desc'] = file_desc_tag.getData() 237 238 if mime_type is not None: 239 file_props['mime-type'] = mime_type 240 file_props['receiver'] = self._ft_get_our_jid() 241 file_props['sid'] = unicode(si.getAttr('id')) 242 file_props['transfered_size'] = [] 243 gajim.socks5queue.add_file_props(self.name, file_props) 244 self.dispatch('FILE_REQUEST', (jid, file_props)) 245 raise xmpp.NodeProcessed
246
247 - def _siErrorCB(self, con, iq_obj):
248 si = iq_obj.getTag('si') 249 profile = si.getAttr('profile') 250 if profile != xmpp.NS_FILE: 251 return 252 file_props = self.files_props.get(iq_obj.getAttr('id')) 253 if not file_props: 254 return 255 jid = self._ft_get_from(iq_obj) 256 file_props['error'] = -3 257 self.dispatch('FILE_REQUEST_ERROR', (jid, file_props, '')) 258 raise xmpp.NodeProcessed
259
260 -class ConnectionSocks5Bytestream(ConnectionBytestream):
261
262 - def send_success_connect_reply(self, streamhost):
263 """ 264 Send reply to the initiator of FT that we made a connection 265 """ 266 if not self.connection or self.connected < 2: 267 return 268 if streamhost is None: 269 return None 270 iq = xmpp.Iq(to=streamhost['initiator'], typ='result', 271 frm=streamhost['target']) 272 iq.setAttr('id', streamhost['id']) 273 query = iq.setTag('query', namespace=xmpp.NS_BYTESTREAM) 274 stream_tag = query.setTag('streamhost-used') 275 stream_tag.setAttr('jid', streamhost['jid']) 276 self.connection.send(iq)
277
278 - def stop_all_active_file_transfers(self, contact):
279 """ 280 Stop all active transfer to or from the given contact 281 """ 282 for file_props in self.files_props.values(): 283 if is_transfer_stopped(file_props): 284 continue 285 receiver_jid = unicode(file_props['receiver']) 286 if contact.get_full_jid() == receiver_jid: 287 file_props['error'] = -5 288 self.remove_transfer(file_props) 289 self.dispatch('FILE_REQUEST_ERROR', (contact.jid, file_props, '')) 290 sender_jid = unicode(file_props['sender']) 291 if contact.get_full_jid() == sender_jid: 292 file_props['error'] = -3 293 self.remove_transfer(file_props)
294
295 - def remove_all_transfers(self):
296 """ 297 Stop and remove all active connections from the socks5 pool 298 """ 299 for file_props in self.files_props.values(): 300 self.remove_transfer(file_props, remove_from_list=False) 301 self.files_props = {}
302
303 - def remove_transfer(self, file_props, remove_from_list=True):
304 if file_props is None: 305 return 306 self.disconnect_transfer(file_props) 307 sid = file_props['sid'] 308 gajim.socks5queue.remove_file_props(self.name, sid) 309 310 if remove_from_list: 311 if 'sid' in self.files_props: 312 del(self.files_props['sid'])
313
314 - def disconnect_transfer(self, file_props):
315 if file_props is None: 316 return 317 if 'hash' in file_props: 318 gajim.socks5queue.remove_sender(file_props['hash']) 319 320 if 'streamhosts' in file_props: 321 for host in file_props['streamhosts']: 322 if 'idx' in host and host['idx'] > 0: 323 gajim.socks5queue.remove_receiver(host['idx']) 324 gajim.socks5queue.remove_sender(host['idx'])
325
326 - def _send_socks5_info(self, file_props):
327 """ 328 Send iq for the present streamhosts and proxies 329 """ 330 if not self.connection or self.connected < 2: 331 return 332 receiver = file_props['receiver'] 333 sender = file_props['sender'] 334 335 sha_str = helpers.get_auth_sha(file_props['sid'], sender, receiver) 336 file_props['sha_str'] = sha_str 337 338 port = gajim.config.get('file_transfers_port') 339 listener = gajim.socks5queue.start_listener(port, sha_str, 340 self._result_socks5_sid, file_props['sid']) 341 if not listener: 342 file_props['error'] = -5 343 self.dispatch('FILE_REQUEST_ERROR', (unicode(receiver), file_props, '')) 344 self._connect_error(unicode(receiver), file_props['sid'], 345 file_props['sid'], code=406) 346 else: 347 iq = xmpp.Iq(to=unicode(receiver), typ='set') 348 file_props['request-id'] = 'id_' + file_props['sid'] 349 iq.setID(file_props['request-id']) 350 query = iq.setTag('query', namespace=xmpp.NS_BYTESTREAM) 351 query.setAttr('mode', 'plain') 352 query.setAttr('sid', file_props['sid']) 353 354 self._add_addiditional_streamhosts_to_query(query, file_props) 355 self._add_local_ips_as_streamhosts_to_query(query, file_props) 356 self._add_proxy_streamhosts_to_query(query, file_props) 357 358 self.connection.send(iq)
359
360 - def _add_streamhosts_to_query(self, query, sender, port, hosts):
361 for host in hosts: 362 streamhost = xmpp.Node(tag='streamhost') 363 query.addChild(node=streamhost) 364 streamhost.setAttr('port', unicode(port)) 365 streamhost.setAttr('host', host) 366 streamhost.setAttr('jid', sender)
367
368 - def _add_local_ips_as_streamhosts_to_query(self, query, file_props):
369 try: 370 my_ips = [self.peerhost[0]] # The ip we're connected to server with 371 # all IPs from local DNS 372 for addr in socket.getaddrinfo(socket.gethostname(), None): 373 if not addr[4][0] in my_ips and not addr[4][0].startswith('127'): 374 my_ips.append(addr[4][0]) 375 376 sender = file_props['sender'] 377 port = gajim.config.get('file_transfers_port') 378 self._add_streamhosts_to_query(query, sender, port, my_ips) 379 except socket.gaierror: 380 self.dispatch('ERROR', (_('Wrong host'), 381 _('Invalid local address? :-O')))
382
383 - def _add_addiditional_streamhosts_to_query(self, query, file_props):
384 sender = file_props['sender'] 385 port = gajim.config.get('file_transfers_port') 386 ft_add_hosts_to_send = gajim.config.get('ft_add_hosts_to_send') 387 additional_hosts = [] 388 if ft_add_hosts_to_send: 389 additional_hosts = [e.strip() for e in ft_add_hosts_to_send.split(',')] 390 else: 391 additional_hosts = [] 392 self._add_streamhosts_to_query(query, sender, port, additional_hosts)
393
394 - def _add_proxy_streamhosts_to_query(self, query, file_props):
395 proxyhosts = self._get_file_transfer_proxies_from_config(file_props) 396 if proxyhosts: 397 file_props['proxy_receiver'] = unicode(file_props['receiver']) 398 file_props['proxy_sender'] = unicode(file_props['sender']) 399 file_props['proxyhosts'] = proxyhosts 400 401 for proxyhost in proxyhosts: 402 self._add_streamhosts_to_query(query, proxyhost['jid'], 403 proxyhost['port'], [proxyhost['host']])
404
405 - def _get_file_transfer_proxies_from_config(self, file_props):
406 configured_proxies = gajim.config.get_per('accounts', self.name, 407 'file_transfer_proxies') 408 shall_use_proxies = gajim.config.get_per('accounts', self.name, 409 'use_ft_proxies') 410 if shall_use_proxies and configured_proxies: 411 proxyhost_dicts = [] 412 proxies = [item.strip() for item in configured_proxies.split(',')] 413 default_proxy = gajim.proxy65_manager.get_default_for_name(self.name) 414 if default_proxy: 415 # add/move default proxy at top of the others 416 if default_proxy in proxies: 417 proxies.remove(default_proxy) 418 proxies.insert(0, default_proxy) 419 420 for proxy in proxies: 421 (host, _port, jid) = gajim.proxy65_manager.get_proxy(proxy, self.name) 422 if not host: 423 continue 424 host_dict = { 425 'state': 0, 426 'target': unicode(file_props['receiver']), 427 'id': file_props['sid'], 428 'sid': file_props['sid'], 429 'initiator': proxy, 430 'host': host, 431 'port': unicode(_port), 432 'jid': jid 433 } 434 proxyhost_dicts.append(host_dict) 435 return proxyhost_dicts 436 else: 437 return []
438
439 - def _result_socks5_sid(self, sid, hash_id):
440 """ 441 Store the result of SHA message from auth 442 """ 443 if sid not in self.files_props: 444 return 445 file_props = self.files_props[sid] 446 file_props['hash'] = hash_id 447 return
448
449 - def _connect_error(self, to, _id, sid, code=404):
450 """ 451 Called when there is an error establishing BS connection, or when 452 connection is rejected 453 """ 454 if not self.connection or self.connected < 2: 455 return 456 msg_dict = { 457 404: 'Could not connect to given hosts', 458 405: 'Cancel', 459 406: 'Not acceptable', 460 } 461 msg = msg_dict[code] 462 iq = xmpp.Iq(to=to, typ='error') 463 iq.setAttr('id', _id) 464 err = iq.setTag('error') 465 err.setAttr('code', unicode(code)) 466 err.setData(msg) 467 self.connection.send(iq) 468 if code == 404: 469 file_props = gajim.socks5queue.get_file_props(self.name, sid) 470 if file_props is not None: 471 self.disconnect_transfer(file_props) 472 file_props['error'] = -3 473 self.dispatch('FILE_REQUEST_ERROR', (to, file_props, msg))
474
475 - def _proxy_auth_ok(self, proxy):
476 """ 477 Called after authentication to proxy server 478 """ 479 if not self.connection or self.connected < 2: 480 return 481 file_props = self.files_props[proxy['sid']] 482 iq = xmpp.Iq(to=proxy['initiator'], typ='set') 483 auth_id = "au_" + proxy['sid'] 484 iq.setID(auth_id) 485 query = iq.setTag('query', namespace=xmpp.NS_BYTESTREAM) 486 query.setAttr('sid', proxy['sid']) 487 activate = query.setTag('activate') 488 activate.setData(file_props['proxy_receiver']) 489 iq.setID(auth_id) 490 self.connection.send(iq)
491 492 # register xmpppy handlers for bytestream and FT stanzas
493 - def _bytestreamErrorCB(self, con, iq_obj):
494 id_ = unicode(iq_obj.getAttr('id')) 495 frm = helpers.get_full_jid_from_iq(iq_obj) 496 query = iq_obj.getTag('query') 497 gajim.proxy65_manager.error_cb(frm, query) 498 jid = helpers.get_jid_from_iq(iq_obj) 499 id_ = id_[3:] 500 if id_ not in self.files_props: 501 return 502 file_props = self.files_props[id_] 503 file_props['error'] = -4 504 self.dispatch('FILE_REQUEST_ERROR', (jid, file_props, '')) 505 raise xmpp.NodeProcessed
506
507 - def _bytestreamSetCB(self, con, iq_obj):
508 target = unicode(iq_obj.getAttr('to')) 509 id_ = unicode(iq_obj.getAttr('id')) 510 query = iq_obj.getTag('query') 511 sid = unicode(query.getAttr('sid')) 512 file_props = gajim.socks5queue.get_file_props(self.name, sid) 513 streamhosts = [] 514 for item in query.getChildren(): 515 if item.getName() == 'streamhost': 516 host_dict = { 517 'state': 0, 518 'target': target, 519 'id': id_, 520 'sid': sid, 521 'initiator': self._ft_get_from(iq_obj) 522 } 523 for attr in item.getAttrs(): 524 host_dict[attr] = item.getAttr(attr) 525 streamhosts.append(host_dict) 526 if file_props is None: 527 if sid in self.files_props: 528 file_props = self.files_props[sid] 529 file_props['fast'] = streamhosts 530 if file_props['type'] == 's': # FIXME: remove fast xmlns 531 # only psi do this 532 if 'streamhosts' in file_props: 533 file_props['streamhosts'].extend(streamhosts) 534 else: 535 file_props['streamhosts'] = streamhosts 536 if not gajim.socks5queue.get_file_props(self.name, sid): 537 gajim.socks5queue.add_file_props(self.name, file_props) 538 gajim.socks5queue.connect_to_hosts(self.name, sid, 539 self.send_success_connect_reply, None) 540 raise xmpp.NodeProcessed 541 542 file_props['streamhosts'] = streamhosts 543 if file_props['type'] == 'r': 544 gajim.socks5queue.connect_to_hosts(self.name, sid, 545 self.send_success_connect_reply, self._connect_error) 546 raise xmpp.NodeProcessed
547
548 - def _ResultCB(self, con, iq_obj):
549 # if we want to respect xep-0065 we have to check for proxy 550 # activation result in any result iq 551 real_id = unicode(iq_obj.getAttr('id')) 552 if not real_id.startswith('au_'): 553 return 554 frm = self._ft_get_from(iq_obj) 555 id_ = real_id[3:] 556 if id_ in self.files_props: 557 file_props = self.files_props[id_] 558 if file_props['streamhost-used']: 559 for host in file_props['proxyhosts']: 560 if host['initiator'] == frm and 'idx' in host: 561 gajim.socks5queue.activate_proxy(host['idx']) 562 raise xmpp.NodeProcessed
563
564 - def _bytestreamResultCB(self, con, iq_obj):
565 frm = self._ft_get_from(iq_obj) 566 real_id = unicode(iq_obj.getAttr('id')) 567 query = iq_obj.getTag('query') 568 gajim.proxy65_manager.resolve_result(frm, query) 569 570 try: 571 streamhost = query.getTag('streamhost-used') 572 except Exception: # this bytestream result is not what we need 573 pass 574 id_ = real_id[3:] 575 if id_ in self.files_props: 576 file_props = self.files_props[id_] 577 else: 578 raise xmpp.NodeProcessed 579 if streamhost is None: 580 # proxy approves the activate query 581 if real_id.startswith('au_'): 582 if 'streamhost-used' not in file_props or \ 583 file_props['streamhost-used'] is False: 584 raise xmpp.NodeProcessed 585 if 'proxyhosts' not in file_props: 586 raise xmpp.NodeProcessed 587 for host in file_props['proxyhosts']: 588 if host['initiator'] == frm and \ 589 unicode(query.getAttr('sid')) == file_props['sid']: 590 gajim.socks5queue.activate_proxy(host['idx']) 591 break 592 raise xmpp.NodeProcessed 593 jid = self._ft_get_streamhost_jid_attr(streamhost) 594 if 'streamhost-used' in file_props and \ 595 file_props['streamhost-used'] is True: 596 raise xmpp.NodeProcessed 597 598 if real_id.startswith('au_'): 599 if 'stopped' in file_props and file_props['stopped']: 600 self.remove_transfer(file_props) 601 else: 602 gajim.socks5queue.send_file(file_props, self.name) 603 raise xmpp.NodeProcessed 604 605 proxy = None 606 if 'proxyhosts' in file_props: 607 for proxyhost in file_props['proxyhosts']: 608 if proxyhost['jid'] == jid: 609 proxy = proxyhost 610 611 if 'stopped' in file_props and file_props['stopped']: 612 self.remove_transfer(file_props) 613 raise xmpp.NodeProcessed 614 if proxy is not None: 615 file_props['streamhost-used'] = True 616 if 'streamhosts' not in file_props: 617 file_props['streamhosts'] = [] 618 file_props['streamhosts'].append(proxy) 619 file_props['is_a_proxy'] = True 620 receiver = Socks5Receiver(gajim.idlequeue, proxy, 621 file_props['sid'], file_props) 622 gajim.socks5queue.add_receiver(self.name, receiver) 623 proxy['idx'] = receiver.queue_idx 624 gajim.socks5queue.on_success = self._proxy_auth_ok 625 raise xmpp.NodeProcessed 626 627 else: 628 gajim.socks5queue.send_file(file_props, self.name) 629 if 'fast' in file_props: 630 fasts = file_props['fast'] 631 if len(fasts) > 0: 632 self._connect_error(frm, fasts[0]['id'], file_props['sid'], 633 code=406) 634 635 raise xmpp.NodeProcessed
636
637 -class ConnectionSocks5BytestreamZeroconf(ConnectionSocks5Bytestream):
638
639 - def _ft_get_from(self, iq_obj):
640 return unicode(iq_obj.getFrom())
641
642 - def _ft_get_our_jid(self):
643 return gajim.get_jid_from_account(self.name)
644
645 - def _ft_get_receiver_jid(self, file_props):
646 return file_props['receiver'].jid
647
648 - def _ft_get_streamhost_jid_attr(self, streamhost):
649 return streamhost.getAttr('jid')
650