Newer
Older
## Copyright (C) 2005-2006 Dimitur Kirov <dkirov AT gmail.com>
## Nikos Kouremenos <kourem AT gmail.com>
## Copyright (C) 2005-2012 Yann Leboulanger <asterix AT lagaule.org>
## Copyright (C) 2006-2008 Jean-Marie Traissard <jim AT lapin.org>
## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org>
## 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
## You should have received a copy of the GNU General Public License
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
from errno import EWOULDBLOCK
from errno import ENOBUFS
from errno import EINTR

Zhenchao Li
committed
import jingle_xtls
if jingle_xtls.PYOPENSSL_PRESENT:
import OpenSSL

Zhenchao Li
committed
import logging
log = logging.getLogger('gajim.c.socks5')
# after foo seconds without activity label transfer as 'stalled'
STALLED_TIMEOUT = 10
# after foo seconds of waiting to connect, disconnect from
# streamhost and try next one
CONNECT_TIMEOUT = 30
# nothing received for the last foo seconds - stop transfer
# if it is 0, then transfer will wait forever
READ_TIMEOUT = 180
# nothing sent for the last foo seconds - stop transfer
# if it is 0, then transfer will wait forever
SEND_TIMEOUT = 180
"""
Queue for all file requests objects
"""
def __init__(self, idlequeue, complete_transfer_cb=None,
self.connected = 0
self.readers = {}
self.files_props = {}
self.senders = {}
self.idx = 1
self.listener = None
self.sha_handlers = {}
# handle all io events in the global idle queue, instead of processing
# each foo seconds
self.idlequeue = idlequeue
self.complete_transfer_cb = complete_transfer_cb
self.progress_transfer_cb = progress_transfer_cb
self.error_cb = error_cb

Yann Leboulanger
committed
self.on_success = {} # {id: cb}
self.on_failure = {} # {id: cb}
def start_listener(self, port, sha_str, sha_handler, fp, fingerprint=None,
"""
Start waiting for incomming connections on (host, port) and do a socks5
authentication using sid for generated SHA
"""
sid = fp['sid']
self.type = type # It says whether we are sending or receiving
self.sha_handlers[sha_str] = (sha_handler, sid)
if self.listener is None or self.listener.connections == []:
self.listener = Socks5Listener(self.idlequeue, port, fp,
fingerprint=fingerprint)
self.listener.queue = self
self.listener.bind()
else:
# There is already a listener, we update the file's information
# on the new connection.
self.listener.file_props = fp
return self.listener
def send_success_reply(self, file_props, streamhost):
if 'streamhost-used' in file_props and \
file_props['streamhost-used'] is True:
if 'proxyhosts' in file_props:
for proxy in file_props['proxyhosts']:
if proxy['host'] == streamhost['host']:
self.on_success[file_props['sid']](proxy)
return 0
if 'streamhosts' in file_props:
for host in file_props['streamhosts']:
if streamhost['state'] == 1:
return 0
streamhost['state'] = 1

Yann Leboulanger
committed
self.on_success[file_props['sid']](streamhost)
return 1
return 0
def connect_to_hosts(self, account, sid, on_success=None, on_failure=None,

Yann Leboulanger
committed
self.on_success[sid] = on_success
self.on_failure[sid] = on_failure
file_props = self.files_props[account][sid]
file_props['failure_cb'] = on_failure
if not file_props['streamhosts']:
on_failure(file_props['sid'])
# add streamhosts to the queue
for streamhost in file_props['streamhosts']:
if 'type' in streamhost and streamhost['type'] == 'proxy':
fp = None
else:
socks5obj = Socks5ReceiverClient(self.idlequeue, streamhost, sid,
file_props, fingerprint=fp)
if 'sha_str' in file_props:
idx = file_props['sha_str']
else:
idx = self.idx
self.idx = self.idx + 1
if 'type' in streamhost and streamhost['type'] == 'proxy':
file_props['is_a_proxy'] = True
file_props['proxy_sender'] = streamhost['target']
file_props['proxy_receiver'] = streamhost['initiator']
socks5obj = Socks5SenderClient(self.idlequeue, idx,
self, _sock=None,host=str(streamhost['host']),
port=int(streamhost['port']),fingerprint=fp,
connected=False, file_props=file_props)
socks5obj.streamhost = streamhost
self.add_sockobj(account, socks5obj, type='sender')
def _socket_connected(self, streamhost, file_props):
"""
Called when there is a host connected to one of the senders's
streamhosts. Stop other attempts for connections
"""
for host in file_props['streamhosts']:
if host != streamhost and 'idx' in host:
if host['state'] == 1:
# remove current
if self.type == 'sender':
self.remove_sender(streamhost['idx'], False)
else:
self.remove_receiver(streamhost['idx'])
return
# set state -2, meaning that this streamhost is stopped,
# but it may be connectected later
if host['state'] >= 0:
if self.type == 'sender':
self.remove_sender(host['idx'], False)
else:
self.remove_receiver(host['idx'])
host['idx'] = -1
host['state'] = -2
def reconnect_client(self, client, streamhost):
"""
Check the state of all streamhosts and if all has failed, then emit
connection failure cb. If there are some which are still not connected
try to establish connection to one of them
"""
self.idlequeue.remove_timeout(client.fd)
self.idlequeue.unplug_idle(client.fd)
file_props = client.file_props
streamhost['state'] = -1
# boolean, indicates that there are hosts, which are not tested yet
unused_hosts = False
for host in file_props['streamhosts']:
if 'idx' in host:
if host['state'] >= 0:
return
elif host['state'] == -2:
unused_hosts = True
if unused_hosts:
for host in file_props['streamhosts']:
if host['state'] == -2:
host['state'] = 0
client = Socks5ReceiverClient(self.idlequeue, host, host['sid'],
file_props)
self.add_sockobj(client.account, client)
host['idx'] = client.queue_idx
# we still have chances to connect
return
if 'received-len' not in file_props or file_props['received-len'] == 0:
# there are no other streamhosts and transfer hasn't started
self._connection_refused(streamhost, file_props, client.queue_idx)
else:
# transfer stopped, it is most likely stopped from sender
file_props['error'] = -1
def _connection_refused(self, streamhost, file_props, idx):
"""
Called when we loose connection during transfer
"""
if file_props is None:
return
streamhost['state'] = -1
# FIXME: should only the receiver be remove? what if we are sending?
self.remove_receiver(idx, False)
if 'streamhosts' in file_props:
for host in file_props['streamhosts']:
if host['state'] != -1:
return
# failure_cb exists - this means that it has never been called
if 'failure_cb' in file_props and file_props['failure_cb']:
del(file_props['failure_cb'])
def add_sockobj(self, account, sockobj, type='receiver'):
Add new file a sockobj type receiver or sender, and use it to connect
to server
self._add(sockobj, self.readers, sockobj.file_props, self.idx)
self._add(sockobj, self.senders, sockobj.file_props, self.idx)
sockobj.queue_idx = self.idx
sockobj.queue = self
sockobj.account = account
self.connected += 1
if result is not None:
result = sockobj.main()
self.process_result(result, sockobj)
return 1
return None
def _add(self, sockobj, sockobjects, fp, hash):
'''
Adds the sockobj to the current list of sockobjects
'''
keys = (fp['sid'], fp['name'], hash)
def result_sha(self, sha_str, idx):
if sha_str in self.sha_handlers:
props = self.sha_handlers[sha_str]
props[0](props[1], idx)
def activate_proxy(self, idx):
if not self.isHashInSockObjs(self.readers, idx):
for key in self.readers.keys():
if idx in key:
reader = self.readers[key]
if reader.file_props['type'] != 's':
return
if reader.state != 5:
return
reader.state = 6
if reader.connected:
reader.file_props['error'] = 0
reader.file_props['disconnect_cb'] = reader.disconnect
reader.file_props['started'] = True
reader.file_props['completed'] = False
reader.file_props['paused'] = False
reader.file_props['stalled'] = False
reader.file_props['elapsed-time'] = 0
reader.file_props['last-time'] = self.idlequeue.current_time()
reader.file_props['received-len'] = 0
reader.pauses = 0
# start sending file to proxy
self.idlequeue.set_read_timeout(reader.fd, STALLED_TIMEOUT)
self.idlequeue.plug_idle(reader, True, False)
result = reader.write_next()
self.process_result(result, reader)
if self.senders == {}:
# Python acts very weird with this. When there is no keys
# in the dictionary It says that it has a key.
# Maybe it is my machine. Without this there is a KeyError
# traceback.
return
log.info("socks5: sending file")
sender = self.senders[key]
file_props['streamhost-used'] = True
sender.account = account
sender.file_props = file_props
result = sender.send_file()
self.process_result(result, sender)
def add_file_props(self, account, file_props):
"""
File_prop to the dict of current file_props. It is identified by account
name and sid
"""
if file_props is None or ('sid' in file_props) is False:
return
_id = file_props['sid']
if account not in self.files_props:
self.files_props[account] = {}
self.files_props[account][_id] = file_props
def remove_file_props(self, account, sid):
if account in self.files_props:
fl_props = self.files_props[account]
if sid in fl_props:
if sid in self.on_success:
del self.on_success[sid]
if sid in self.on_failure:
del self.on_failure[sid]
del(fl_props[sid])
if len(self.files_props) == 0:
self.connected = 0
def get_file_props(self, account, sid):
"""
Get fil_prop by account name and session id
"""
if account in self.files_props:
fl_props = self.files_props[account]
if sid in fl_props:
return fl_props[sid]
return None
def isHashInSockObjs(self, sockobjs, hash):
'''
It tells wether there is a particular hash in sockobjs or not
'''
for key in sockobjs:
if hash in key:
return True
return False
def on_connection_accepted(self, sock, listener):
sock_hash = sock.__hash__()
not self.isHashInSockObjs(self.senders, sock_hash):
sock[0], sock[1][0], sock[1][1], fingerprint='server',
file_props=listener.file_props)
self._add(sockobj, self.senders, listener.file_props, sock_hash)
self.idlequeue.plug_idle(sockobj, False, True)
self.connected += 1
if self.type == 'receiver' and \
not self.isHashInSockObjs(self.readers, sock_hash):
sh = {}
sh['host'] = sock[1][0]
sh['port'] = sock[1][1]
sh['initiator'] = None
sh['target'] = None
streamhost=sh,sid=None, file_props=listener.file_props,
self._add(sockobj, self.readers, listener.file_props, sock_hash)
sockobj.set_sock(sock[0])
sockobj.queue = self
def process_result(self, result, actor):
"""
Take appropriate actions upon the result:
[ 0, - 1 ] complete/end transfer
[ > 0 ] send progress message
[ None ] do nothing
"""
if result is None:
return
if result in (0, -1) and self.complete_transfer_cb is not None:
account = actor.account
if account is None and 'tt_account' in actor.file_props:
account = actor.file_props['tt_account']
self.complete_transfer_cb(account, actor.file_props)
elif self.progress_transfer_cb is not None:
self.progress_transfer_cb(actor.account, actor.file_props)
def remove_receiver(self, idx, do_disconnect=True, remove_all=False):
"""
Remove reciver from the list and decrease the number of active
connections with 1
"""
if idx != -1:
for key in self.readers.keys():
if idx in key:
reader = self.readers[key]
self.idlequeue.unplug_idle(reader.fd)
self.idlequeue.remove_timeout(reader.fd)
if do_disconnect:
reader.disconnect()
else:
if reader.streamhost is not None:
reader.streamhost['state'] = -1
del(self.readers[key])
if not remove_all:
break
def remove_sender(self, idx, do_disconnect=True, remove_all=False):
"""
Remove sender from the list of senders and decrease the number of active
connections with 1
"""
if idx != -1:
for key in self.senders.keys():
if idx in key:
sender = self.senders[key]
if do_disconnect:
sender.disconnect()
else:
self.idlequeue.unplug_idle(sender.fd)
self.idlequeue.remove_timeout(sender.fd)
del(self.senders[key])
if self.connected > 0:
self.connected -= 1
if len(self.senders) == 0 and self.listener is not None:
self.listener.disconnect()
self.listener = None
self.connected -= 1
def __init__(self, idlequeue, host, port, initiator, target, sid):
if host is not None:
try:
self.host = host
self.ais = socket.getaddrinfo(host, port, socket.AF_UNSPEC,
except socket.gaierror:
self.ais = None
self.idlequeue = idlequeue
self.fd = -1
self.port = port
self.initiator = initiator
self.target = target
self.sid = sid
self._sock = None
self.account = None
self.state = 0 # not connected
self.pauses = 0
self.size = 0
self.remaining_buff = ''
self.file = None
self.type = ''
def _is_connected(self):
if self.state < 5:
return False
return True
def connect(self):
"""
Create the socket and plug it to the idlequeue
"""
if self.ais is None:
return None
for ai in self.ais:
try:
self._sock = socket.socket(*ai[:3])
if not self.fingerprint is None:
self._sock = OpenSSL.SSL.Connection(
jingle_xtls.get_context('client'), self._sock)
# this will not block the GUI
self._sock.setblocking(False)
self._server = ai[4]
break
except socket.error, e:
if not isinstance(e, basestring) and e[0] == EINPROGRESS:
break
# for all other errors, we try other addresses
continue
self.fd = self._sock.fileno()
self.state = 0 # about to be connected
self.idlequeue.plug_idle(self, True, False)
self.do_connect()
self.idlequeue.set_read_timeout(self.fd, CONNECT_TIMEOUT)
return None
def do_connect(self):
#self._sock.setblocking(True)
self._sock.connect(self._server)
self._sock.setblocking(False)
self._send=self._sock.send
self._recv=self._sock.recv
except Exception, ee:
errnum = ee[0]
self.connect_timeout += 1
if errnum == 111 or self.connect_timeout > 1000:
self.queue._connection_refused(self.streamhost, self.file_props,
self.queue_idx)
self.connected = False
return None
# win32 needs this
elif errnum not in (10056, EISCONN) or self.state != 0:
return None
else: # socket is already connected
self._sock.setblocking(False)
self._send=self._sock.send
self._recv=self._sock.recv
self.buff = ''
self.connected = True
self.file_props['connected'] = True
self.file_props['disconnect_cb'] = self.disconnect
self.file_props['paused'] = False
self.state = 1 # connected
# stop all others connections to sender's streamhosts
self.queue._socket_connected(self.streamhost, self.file_props)
self.idlequeue.plug_idle(self, True, False)
return 1 # we are connected
def read_timeout(self):
self.idlequeue.remove_timeout(self.fd)
if self.state > 5:
# no activity for foo seconds
if self.file_props['stalled'] == False:
self.file_props['stalled'] = True
self.queue.process_result(-1, self)
if 'received-len' not in self.file_props:
self.file_props['received-len'] = 0
if SEND_TIMEOUT > 0:
self.idlequeue.set_read_timeout(self.fd, SEND_TIMEOUT)
else:
# stop transfer, there is no error code for this
self.pollend()
self.queue.reconnect_client(self, self.streamhost)
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
def open_file_for_reading(self):
if self.file is None:
try:
self.file = open(self.file_props['file-name'], 'rb')
if 'offset' in self.file_props and self.file_props['offset']:
self.size = self.file_props['offset']
self.file.seek(self.size)
self.file_props['received-len'] = self.size
except IOError, e:
self.close_file()
raise IOError, e
def close_file(self):
if self.file:
if not self.file.closed:
try:
self.file.close()
except Exception:
pass
self.file = None
def get_fd(self):
"""
Test if file is already open and return its fd, or just open the file and
return the fd
"""
if 'fd' in self.file_props:
fd = self.file_props['fd']
else:
offset = 0
opt = 'wb'
if 'offset' in self.file_props and self.file_props['offset']:
offset = self.file_props['offset']
opt = 'ab'
fd = open(self.file_props['file-name'], opt)
self.file_props['fd'] = fd
self.file_props['elapsed-time'] = 0
self.file_props['last-time'] = self.idlequeue.current_time()
self.file_props['received-len'] = offset
return fd
def rem_fd(self, fd):
if 'fd' in self.file_props:
del(self.file_props['fd'])
try:
fd.close()
except Exception:
pass
def receive(self):
"""
Read small chunks of data. Call owner's disconnected() method if
appropriate
"""
received = ''
try:
add = self._recv(64)
except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError,
log.info('SSL rehandshake request : ' + repr(e))
raise e
except Exception:
add = ''
received += add
if len(add) == 0:
self.disconnect()
return add
def send_raw(self, raw_data):
"""
Write raw outgoing data
"""
try:
self._send(raw_data)
except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError,
log.info('SSL rehandshake request :' + repr(e))
raise e
except Exception, e:
self.disconnect()
return len(raw_data)
def write_next(self):
if self.remaining_buff != '':
buff = self.remaining_buff
self.remaining_buff = ''
else:
try:
self.open_file_for_reading()
except IOError, e:
self.state = 8 # end connection
self.disconnect()
self.file_props['error'] = -7 # unable to read from file
return -1
buff = self.file.read(MAX_BUFF_LEN)
if len(buff) > 0:
lenn = 0
try:
lenn = self._send(buff)
except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError,
log.info('SSL rehandshake request :' + repr(e))
raise e
except Exception, e:
if e.args[0] not in (EINTR, ENOBUFS, EWOULDBLOCK):
# peer stopped reading
self.state = 8 # end connection
self.disconnect()
self.file_props['error'] = -1
return -1
self.size += lenn
current_time = self.idlequeue.current_time()
self.file_props['elapsed-time'] += current_time - \
self.file_props['last-time'] = current_time
self.file_props['received-len'] = self.size
if self.size >= int(self.file_props['size']):
self.state = 8 # end connection
self.file_props['error'] = 0
self.disconnect()
return -1
if lenn != len(buff):
self.remaining_buff = buff[lenn:]
else:
self.remaining_buff = ''
self.state = 7 # continue to write in the socket
if lenn == 0:
return None
self.file_props['stalled'] = False
return lenn
else:
self.state = 8 # end connection
self.disconnect()
return -1
def get_file_contents(self, timeout):
"""
Read file contents from socket and write them to file
"""
if self.file_props is None or ('file-name' in self.file_props) is False:
self.file_props['error'] = -2
return None
fd = None
if self.remaining_buff != '':
try:
fd = self.get_fd()
except IOError, e:
self.disconnect(False)
self.file_props['error'] = -6 # file system error
return 0
fd.write(self.remaining_buff)
lenn = len(self.remaining_buff)
current_time = self.idlequeue.current_time()
self.file_props['elapsed-time'] += current_time - \
self.file_props['last-time'] = current_time
self.file_props['received-len'] += lenn
self.remaining_buff = ''
if self.file_props['received-len'] == int(self.file_props['size']):
self.rem_fd(fd)
self.disconnect()
self.file_props['error'] = 0
self.file_props['completed'] = True
return 0
else:
try:
fd = self.get_fd()
except IOError, e:
self.disconnect(False)
self.file_props['error'] = -6 # file system error
return 0
try:
buff = self._recv(MAX_BUFF_LEN)
except (OpenSSL.SSL.WantReadError, OpenSSL.SSL.WantWriteError,
log.info('SSL rehandshake request :' + repr(e))
raise e
except Exception:
buff = ''
current_time = self.idlequeue.current_time()
self.file_props['elapsed-time'] += current_time - \
self.file_props['last-time'] = current_time
self.file_props['received-len'] += len(buff)
if len(buff) == 0:
# Transfer stopped somehow:
# reset, paused or network error
self.rem_fd(fd)
self.file_props['error'] = -1
return 0
try:
fd.write(buff)
except IOError, e:
self.rem_fd(fd)
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
self.file_props['error'] = -6 # file system error
return 0
if self.file_props['received-len'] >= int(self.file_props['size']):
# transfer completed
self.rem_fd(fd)
self.disconnect()
self.file_props['error'] = 0
self.file_props['completed'] = True
return 0
# return number of read bytes. It can be used in progressbar
if fd is not None:
self.file_props['stalled'] = False
if fd is None and self.file_props['stalled'] is False:
return None
if 'received-len' in self.file_props:
if self.file_props['received-len'] != 0:
return self.file_props['received-len']
return None
def disconnect(self):
"""
Close open descriptors and remover socket descr. from idleque
"""
# be sure that we don't leave open file
self.close_file()
self.idlequeue.remove_timeout(self.fd)
self.idlequeue.unplug_idle(self.fd)
try:
self.queue.listener.connections.remove(self._sock)
except ValueError:
pass # Not in list
if self.queue.listener.connections == []:
self.queue.listener.disconnect()
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
try:
self._sock.shutdown(socket.SHUT_RDWR)
self._sock.close()
except Exception:
# socket is already closed
pass
self.connected = False
self.fd = -1
self.state = -1
def _get_auth_buff(self):
"""
Message, that we support 1 one auth mechanism: the 'no auth' mechanism
"""
return struct.pack('!BBB', 0x05, 0x01, 0x00)
def _parse_auth_buff(self, buff):
"""
Parse the initial message and create a list of auth mechanisms
"""
auth_mechanisms = []
try:
num_auth = struct.unpack('!xB', buff[:2])[0]
for i in xrange(num_auth):
mechanism, = struct.unpack('!B', buff[1 + i])
auth_mechanisms.append(mechanism)
except Exception:
return None
return auth_mechanisms
def _get_auth_response(self):
"""
Socks version(5), number of extra auth methods (we send 0x00 - no auth)
"""
return struct.pack('!BB', 0x05, 0x00)
def _get_connect_buff(self):
buff = struct.pack('!BBBBB%dsBB' % len(self.host),
0x05, 0x01, 0x00, 0x03, len(self.host), self.host, self.port >> 8,
self.port & 0xff)
return buff
def _get_request_buff(self, msg, command = 0x01):
"""
Connect request by domain name, sid sha, instead of domain name (jep
0096)
"""
buff = struct.pack('!BBBBB%dsBB' % len(msg),
0x05, command, 0x00, 0x03, len(msg), msg, 0, 0)
return buff
def _parse_request_buff(self, buff):
try: # don't trust on what comes from the outside
req_type, host_type, = struct.unpack('!xBxB', buff[:4])
if host_type == 0x01:
host_arr = struct.unpack('!iiii', buff[4:8])
host, = '.'.join(str(s) for s in host_arr)
host_len = len(host)
elif host_type == 0x03:
host_len, = struct.unpack('!B', buff[4])
host, = struct.unpack('!%ds' % host_len, buff[5:5 + host_len])
portlen = len(buff[host_len + 5:])
if portlen == 1:
port, = struct.unpack('!B', buff[host_len + 5])
elif portlen == 2:
port, = struct.unpack('!H', buff[host_len + 5:])
# file data, comes with auth message (Gaim bug)
else:
port, = struct.unpack('!H', buff[host_len + 5: host_len + 7])
self.remaining_buff = buff[host_len + 7:]
except Exception:
return (None, None, None)
return (req_type, host, port)
def read_connect(self):
"""
Connect response: version, auth method
"""
try:
buff = self._recv()
except (SSL.WantReadError, SSL.WantWriteError,
SSL.WantX509LookupError), e:
log.info("SSL rehandshake request : " + repr(e))
raise e
try:
version, method = struct.unpack('!BB', buff)
except Exception:
version, method = None, None
if version != 0x05 or method == 0xff:
self.disconnect()
def continue_paused_transfer(self):
if self.state < 5:
return
if self.file_props['type'] == 'r':
self.idlequeue.plug_idle(self, False, True)
else:
self.idlequeue.plug_idle(self, True, False)
def _get_sha1_auth(self):
"""
Get sha of sid + Initiator jid + Target jid
"""
if 'is_a_proxy' in self.file_props:
del(self.file_props['is_a_proxy'])
self.file_props['proxy_sender'],
self.file_props['proxy_receiver'])).hexdigest()
return hashlib.sha1('%s%s%s' % (self.sid, self.initiator, self.target)).\
hexdigest()
"""
Class for sending file to socket over socks5
"""
port=None, fingerprint = None, connected=True, file_props={}):
self.fingerprint = fingerprint
self.queue_idx = sock_hash
self.queue = parent
self.file_props = file_props
if self.fingerprint is not None:
jingle_xtls.get_context('server'), _sock)
self.fd = _sock.fileno()
self._recv = _sock.recv
self._send = _sock.send
self.connected = connected
self.state = 1 # waiting for first bytes
self.connect_timeout = 0
self.file_props['error'] = 0
self.file_props['disconnect_cb'] = self.disconnect
self.file_props['started'] = True
self.file_props['completed'] = False
self.file_props['paused'] = False
self.file_props['continue_cb'] = self.continue_paused_transfer
self.file_props['stalled'] = False
self.file_props['connected'] = True
self.file_props['elapsed-time'] = 0
self.file_props['last-time'] = self.idlequeue.current_time()
self.file_props['received-len'] = 0
self.type = 'sender'
def start_transfer(self):
"""
Send the file
"""
return self.write_next()
def set_connection_sock(self, _sock):
self._sock = _sock
if self.fingerprint is not None:
self._sock = OpenSSL.SSL.Connection(
jingle_xtls.get_context('client'), self._sock)
else:
self._sock.setblocking(False)