coding standards

This commit is contained in:
Yann Leboulanger 2008-11-24 17:00:20 +00:00
parent 482cb1ee1d
commit 04e88bab3c

View file

@ -68,7 +68,7 @@ class SocksQueue:
self.error_cb = error_cb self.error_cb = error_cb
self.on_success = None self.on_success = None
self.on_failure = None self.on_failure = None
def start_listener(self, port, sha_str, sha_handler, sid): def start_listener(self, port, sha_str, sha_handler, sid):
''' start waiting for incomming connections on (host, port) ''' start waiting for incomming connections on (host, port)
and do a socks5 authentication using sid for generated sha and do a socks5 authentication using sid for generated sha
@ -87,16 +87,16 @@ class SocksQueue:
return None return None
self.connected += 1 self.connected += 1
return self.listener return self.listener
def send_success_reply(self, file_props, streamhost): def send_success_reply(self, file_props, streamhost):
if 'streamhost-used' in file_props and \ if 'streamhost-used' in file_props and \
file_props['streamhost-used'] is True: file_props['streamhost-used'] is True:
if 'proxyhosts' in file_props: if 'proxyhosts' in file_props:
for proxy in file_props['proxyhosts']: for proxy in file_props['proxyhosts']:
if proxy == streamhost: if proxy == streamhost:
self.on_success(streamhost) self.on_success(streamhost)
return 2 return 2
return 0 return 0
if 'streamhosts' in file_props: if 'streamhosts' in file_props:
for host in file_props['streamhosts']: for host in file_props['streamhosts']:
if streamhost['state'] == 1: if streamhost['state'] == 1:
@ -105,22 +105,21 @@ class SocksQueue:
self.on_success(streamhost) self.on_success(streamhost)
return 1 return 1
return 0 return 0
def connect_to_hosts(self, account, sid, on_success = None, def connect_to_hosts(self, account, sid, on_success=None, on_failure=None):
on_failure = None):
self.on_success = on_success self.on_success = on_success
self.on_failure = on_failure self.on_failure = on_failure
file_props = self.files_props[account][sid] file_props = self.files_props[account][sid]
file_props['failure_cb'] = on_failure file_props['failure_cb'] = on_failure
# add streamhosts to the queue # add streamhosts to the queue
for streamhost in file_props['streamhosts']: for streamhost in file_props['streamhosts']:
receiver = Socks5Receiver(self.idlequeue, streamhost, sid, file_props) receiver = Socks5Receiver(self.idlequeue, streamhost, sid, file_props)
self.add_receiver(account, receiver) self.add_receiver(account, receiver)
streamhost['idx'] = receiver.queue_idx streamhost['idx'] = receiver.queue_idx
def _socket_connected(self, streamhost, file_props): def _socket_connected(self, streamhost, file_props):
''' called when there is a host connected to one of the ''' called when there is a host connected to one of the
senders's streamhosts. Stop othere attempts for connections ''' senders's streamhosts. Stop othere attempts for connections '''
for host in file_props['streamhosts']: for host in file_props['streamhosts']:
if host != streamhost and 'idx' in host: if host != streamhost and 'idx' in host:
@ -130,14 +129,14 @@ class SocksQueue:
return return
# set state -2, meaning that this streamhost is stopped, # set state -2, meaning that this streamhost is stopped,
# but it may be connectected later # but it may be connectected later
if host['state'] >=0: if host['state'] >= 0:
self.remove_receiver(host['idx']) self.remove_receiver(host['idx'])
host['idx'] = -1 host['idx'] = -1
host['state'] = -2 host['state'] = -2
def reconnect_receiver(self, receiver, streamhost): def reconnect_receiver(self, receiver, streamhost):
''' Check the state of all streamhosts and if all has failed, then ''' Check the state of all streamhosts and if all has failed, then
emit connection failure cb. If there are some which are still emit connection failure cb. If there are some which are still
not connected try to establish connection to one of them. not connected try to establish connection to one of them.
''' '''
self.idlequeue.remove_timeout(receiver.fd) self.idlequeue.remove_timeout(receiver.fd)
@ -156,7 +155,8 @@ class SocksQueue:
for host in file_props['streamhosts']: for host in file_props['streamhosts']:
if host['state'] == -2: if host['state'] == -2:
host['state'] = 0 host['state'] = 0
receiver = Socks5Receiver(self.idlequeue, host, host['sid'], file_props) receiver = Socks5Receiver(self.idlequeue, host, host['sid'],
file_props)
self.add_receiver(receiver.account, receiver) self.add_receiver(receiver.account, receiver)
host['idx'] = receiver.queue_idx host['idx'] = receiver.queue_idx
# we still have chances to connect # we still have chances to connect
@ -169,7 +169,7 @@ class SocksQueue:
receiver.disconnect() receiver.disconnect()
file_props['error'] = -1 file_props['error'] = -1
self.process_result(-1, receiver) self.process_result(-1, receiver)
def _connection_refused(self, streamhost, file_props, idx): def _connection_refused(self, streamhost, file_props, idx):
''' cb, called when we loose connection during transfer''' ''' cb, called when we loose connection during transfer'''
if file_props is None: if file_props is None:
@ -182,10 +182,10 @@ class SocksQueue:
return return
# failure_cb exists - this means that it has never been called # failure_cb exists - this means that it has never been called
if 'failure_cb' in file_props and file_props['failure_cb']: if 'failure_cb' in file_props and file_props['failure_cb']:
file_props['failure_cb'](streamhost['initiator'], streamhost['id'], file_props['failure_cb'](streamhost['initiator'], streamhost['id'],
file_props['sid'], code = 404) file_props['sid'], code = 404)
del(file_props['failure_cb']) del(file_props['failure_cb'])
def add_receiver(self, account, sock5_receiver): def add_receiver(self, account, sock5_receiver):
''' add new file request ''' ''' add new file request '''
self.readers[self.idx] = sock5_receiver self.readers[self.idx] = sock5_receiver
@ -200,23 +200,21 @@ class SocksQueue:
self.process_result(result, sock5_receiver) self.process_result(result, sock5_receiver)
return 1 return 1
return None return None
def get_file_from_sender(self, file_props, account): def get_file_from_sender(self, file_props, account):
if file_props is None: if file_props is None:
return return
if 'hash' in file_props and \ if 'hash' in file_props and file_props['hash'] in self.senders:
file_props['hash'] in self.senders:
sender = self.senders[file_props['hash']] sender = self.senders[file_props['hash']]
sender.account = account sender.account = account
result = self.get_file_contents(0) result = self.get_file_contents(0)
self.process_result(result, sender) self.process_result(result, sender)
def result_sha(self, sha_str, idx): def result_sha(self, sha_str, idx):
if sha_str in self.sha_handlers: if sha_str in self.sha_handlers:
props = self.sha_handlers[sha_str] props = self.sha_handlers[sha_str]
props[0](props[1], idx) props[0](props[1], idx)
def activate_proxy(self, idx): def activate_proxy(self, idx):
if idx not in self.readers: if idx not in self.readers:
return return
@ -242,15 +240,14 @@ class SocksQueue:
self.idlequeue.plug_idle(reader, True, False) self.idlequeue.plug_idle(reader, True, False)
result = reader.write_next() result = reader.write_next()
self.process_result(result, reader) self.process_result(result, reader)
def send_file(self, file_props, account): def send_file(self, file_props, account):
if 'hash' in file_props and \ if 'hash' in file_props and file_props['hash'] in self.senders:
file_props['hash'] in self.senders:
sender = self.senders[file_props['hash']] sender = self.senders[file_props['hash']]
file_props['streamhost-used'] = True file_props['streamhost-used'] = True
sender.account = account sender.account = account
if file_props['type'] == 's': if file_props['type'] == 's':
sender.file_props = file_props sender.file_props = file_props
result = sender.send_file() result = sender.send_file()
self.process_result(result, sender) self.process_result(result, sender)
else: else:
@ -258,28 +255,27 @@ class SocksQueue:
file_props['last-time'] = self.idlequeue.current_time() file_props['last-time'] = self.idlequeue.current_time()
file_props['received-len'] = 0 file_props['received-len'] = 0
sender.file_props = file_props sender.file_props = file_props
def add_file_props(self, account, file_props): def add_file_props(self, account, file_props):
''' file_prop to the dict of current file_props. ''' file_prop to the dict of current file_props.
It is identified by account name and sid It is identified by account name and sid
''' '''
if file_props is None or \ if file_props is None or ('sid' in file_props) is False:
('sid' in file_props) is False:
return return
_id = file_props['sid'] _id = file_props['sid']
if account not in self.files_props: if account not in self.files_props:
self.files_props[account] = {} self.files_props[account] = {}
self.files_props[account][_id] = file_props self.files_props[account][_id] = file_props
def remove_file_props(self, account, sid): def remove_file_props(self, account, sid):
if account in self.files_props: if account in self.files_props:
fl_props = self.files_props[account] fl_props = self.files_props[account]
if sid in fl_props: if sid in fl_props:
del(fl_props[sid]) del(fl_props[sid])
if len(self.files_props) == 0: if len(self.files_props) == 0:
self.connected = 0 self.connected = 0
def get_file_props(self, account, sid): def get_file_props(self, account, sid):
''' get fil_prop by account name and session id ''' ''' get fil_prop by account name and session id '''
if account in self.files_props: if account in self.files_props:
@ -287,14 +283,14 @@ class SocksQueue:
if sid in fl_props: if sid in fl_props:
return fl_props[sid] return fl_props[sid]
return None return None
def on_connection_accepted(self, sock): def on_connection_accepted(self, sock):
sock_hash = sock.__hash__() sock_hash = sock.__hash__()
if sock_hash not in self.senders: if sock_hash not in self.senders:
self.senders[sock_hash] = Socks5Sender(self.idlequeue, self.senders[sock_hash] = Socks5Sender(self.idlequeue, sock_hash, self,
sock_hash, self, sock[0], sock[1][0], sock[1][1]) sock[0], sock[1][0], sock[1][1])
self.connected += 1 self.connected += 1
def process_result(self, result, actor): def process_result(self, result, actor):
''' Take appropriate actions upon the result: ''' Take appropriate actions upon the result:
[ 0, - 1 ] complete/end transfer [ 0, - 1 ] complete/end transfer
@ -310,9 +306,9 @@ class SocksQueue:
self.complete_transfer_cb(account, actor.file_props) self.complete_transfer_cb(account, actor.file_props)
elif self.progress_transfer_cb is not None: elif self.progress_transfer_cb is not None:
self.progress_transfer_cb(actor.account, actor.file_props) self.progress_transfer_cb(actor.account, actor.file_props)
def remove_receiver(self, idx, do_disconnect = True): def remove_receiver(self, idx, do_disconnect=True):
''' Remove reciver from the list and decrease ''' Remove reciver from the list and decrease
the number of active connections with 1''' the number of active connections with 1'''
if idx != -1: if idx != -1:
if idx in self.readers: if idx in self.readers:
@ -323,11 +319,11 @@ class SocksQueue:
reader.disconnect() reader.disconnect()
else: else:
if reader.streamhost is not None: if reader.streamhost is not None:
reader.streamhost['state'] = -1 reader.streamhost['state'] = -1
del(self.readers[idx]) del(self.readers[idx])
def remove_sender(self, idx, do_disconnect = True): def remove_sender(self, idx, do_disconnect=True):
''' Remove sender from the list of senders and decrease the ''' Remove sender from the list of senders and decrease the
number of active connections with 1''' number of active connections with 1'''
if idx != -1: if idx != -1:
if idx in self.senders: if idx in self.senders:
@ -342,13 +338,14 @@ class SocksQueue:
self.listener.disconnect() self.listener.disconnect()
self.listener = None self.listener = None
self.connected -= 1 self.connected -= 1
class Socks5: class Socks5:
def __init__(self, idlequeue, host, port, initiator, target, sid): def __init__(self, idlequeue, host, port, initiator, target, sid):
if host is not None: if host is not None:
try: try:
self.host = host self.host = host
self.ais = socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_STREAM) self.ais = socket.getaddrinfo(host, port, socket.AF_UNSPEC,
socket.SOCK_STREAM)
except socket.gaierror: except socket.gaierror:
self.ais = None self.ais = None
self.idlequeue = idlequeue self.idlequeue = idlequeue
@ -364,7 +361,7 @@ class Socks5:
self.size = 0 self.size = 0
self.remaining_buff = '' self.remaining_buff = ''
self.file = None self.file = None
def open_file_for_reading(self): def open_file_for_reading(self):
if self.file is None: if self.file is None:
try: try:
@ -376,7 +373,7 @@ class Socks5:
except IOError, e: except IOError, e:
self.close_file() self.close_file()
raise IOError, e raise IOError, e
def close_file(self): def close_file(self):
if self.file: if self.file:
if not self.file.closed: if not self.file.closed:
@ -385,7 +382,7 @@ class Socks5:
except Exception: except Exception:
pass pass
self.file = None self.file = None
def get_fd(self): def get_fd(self):
''' Test if file is already open and return its fd, ''' Test if file is already open and return its fd,
or just open the file and return the fd. or just open the file and return the fd.
@ -404,7 +401,7 @@ class Socks5:
self.file_props['last-time'] = self.idlequeue.current_time() self.file_props['last-time'] = self.idlequeue.current_time()
self.file_props['received-len'] = offset self.file_props['received-len'] = offset
return fd return fd
def rem_fd(self, fd): def rem_fd(self, fd):
if 'fd' in self.file_props: if 'fd' in self.file_props:
del(self.file_props['fd']) del(self.file_props['fd'])
@ -412,21 +409,20 @@ class Socks5:
fd.close() fd.close()
except Exception: except Exception:
pass pass
def receive(self): def receive(self):
''' Reads small chunks of data. ''' Reads small chunks of data.
Calls owner's disconnected() method if appropriate.''' Calls owner's disconnected() method if appropriate.'''
received = '' received = ''
try: try:
add = self._recv(64) add = self._recv(64)
except Exception, e: except Exception, e:
add='' add = ''
received +=add received += add
if len(add) == 0: if len(add) == 0:
self.disconnect() self.disconnect()
return add return add
def send_raw(self,raw_data): def send_raw(self,raw_data):
''' Writes raw outgoing data. ''' ''' Writes raw outgoing data. '''
try: try:
@ -434,7 +430,7 @@ class Socks5:
except Exception, e: except Exception, e:
self.disconnect() self.disconnect()
return len(raw_data) return len(raw_data)
def write_next(self): def write_next(self):
if self.remaining_buff != '': if self.remaining_buff != '':
buff = self.remaining_buff buff = self.remaining_buff
@ -483,12 +479,10 @@ class Socks5:
self.state = 8 # end connection self.state = 8 # end connection
self.disconnect() self.disconnect()
return -1 return -1
def get_file_contents(self, timeout): def get_file_contents(self, timeout):
''' read file contents from socket and write them to file ''', \ ''' read file contents from socket and write them to file '''
self.file_props['type'], self.file_props['sid'] if self.file_props is None or ('file-name' in self.file_props) is False:
if self.file_props is None or \
('file-name' in self.file_props) is False:
self.file_props['error'] = -2 self.file_props['error'] = -2
return None return None
fd = None fd = None
@ -510,7 +504,7 @@ class Socks5:
return 0 return 0
else: else:
fd = self.get_fd() fd = self.get_fd()
try: try:
buff = self._recv(MAX_BUFF_LEN) buff = self._recv(MAX_BUFF_LEN)
except Exception, e: except Exception, e:
buff = '' buff = ''
@ -549,7 +543,7 @@ class Socks5:
if self.file_props['received-len'] != 0: if self.file_props['received-len'] != 0:
return self.file_props['received-len'] return self.file_props['received-len']
return None return None
def disconnect(self): def disconnect(self):
''' Closes open descriptors and remover socket descr. from idleque ''' ''' Closes open descriptors and remover socket descr. from idleque '''
# be sure that we don't leave open file # be sure that we don't leave open file
@ -565,12 +559,12 @@ class Socks5:
self.connected = False self.connected = False
self.fd = -1 self.fd = -1
self.state = -1 self.state = -1
def _get_auth_buff(self): def _get_auth_buff(self):
''' Message, that we support 1 one auth mechanism: ''' Message, that we support 1 one auth mechanism:
the 'no auth' mechanism. ''' the 'no auth' mechanism. '''
return struct.pack('!BBB', 0x05, 0x01, 0x00) return struct.pack('!BBB', 0x05, 0x01, 0x00)
def _parse_auth_buff(self, buff): def _parse_auth_buff(self, buff):
''' Parse the initial message and create a list of auth ''' Parse the initial message and create a list of auth
mechanisms ''' mechanisms '''
@ -583,30 +577,31 @@ class Socks5:
except Exception: except Exception:
return None return None
return auth_mechanisms return auth_mechanisms
def _get_auth_response(self): def _get_auth_response(self):
''' socks version(5), number of extra auth methods (we send ''' socks version(5), number of extra auth methods (we send
0x00 - no auth 0x00 - no auth
) ''' ) '''
return struct.pack('!BB', 0x05, 0x00) return struct.pack('!BB', 0x05, 0x00)
def _get_connect_buff(self): def _get_connect_buff(self):
''' Connect request by domain name ''' ''' Connect request by domain name '''
buff = struct.pack('!BBBBB%dsBB' % len(self.host), buff = struct.pack('!BBBBB%dsBB' % len(self.host),
0x05, 0x01, 0x00, 0x03, len(self.host), self.host, 0x05, 0x01, 0x00, 0x03, len(self.host), self.host,
self.port >> 8, self.port & 0xff) self.port >> 8, self.port & 0xff)
return buff return buff
def _get_request_buff(self, msg, command = 0x01): def _get_request_buff(self, msg, command = 0x01):
''' Connect request by domain name, ''' Connect request by domain name,
sid sha, instead of domain name (jep 0096) ''' sid sha, instead of domain name (jep 0096) '''
buff = struct.pack('!BBBBB%dsBB' % len(msg), buff = struct.pack('!BBBBB%dsBB' % len(msg),
0x05, command, 0x00, 0x03, len(msg), msg, 0, 0) 0x05, command, 0x00, 0x03, len(msg), msg, 0, 0)
return buff return buff
def _parse_request_buff(self, buff): def _parse_request_buff(self, buff):
try: # don't trust on what comes from the outside try: # don't trust on what comes from the outside
version, req_type, reserved, host_type, = \ version, req_type, reserved, host_type, = struct.unpack('!BBBB',
struct.unpack('!BBBB', buff[:4]) buff[:4])
if host_type == 0x01: if host_type == 0x01:
host_arr = struct.unpack('!iiii', buff[4:8]) host_arr = struct.unpack('!iiii', buff[4:8])
host, = '.'.join(str(s) for s in host_arr) host, = '.'.join(str(s) for s in host_arr)
@ -615,18 +610,18 @@ class Socks5:
host_len, = struct.unpack('!B' , buff[4]) host_len, = struct.unpack('!B' , buff[4])
host, = struct.unpack('!%ds' % host_len, buff[5:5 + host_len]) host, = struct.unpack('!%ds' % host_len, buff[5:5 + host_len])
portlen = len(buff[host_len + 5:]) portlen = len(buff[host_len + 5:])
if portlen == 1: if portlen == 1:
port, = struct.unpack('!B', buff[host_len + 5]) port, = struct.unpack('!B', buff[host_len + 5])
elif portlen == 2: elif portlen == 2:
port, = struct.unpack('!H', buff[host_len + 5:]) port, = struct.unpack('!H', buff[host_len + 5:])
# file data, comes with auth message (Gaim bug) # file data, comes with auth message (Gaim bug)
else: else:
port, = struct.unpack('!H', buff[host_len + 5: host_len + 7]) port, = struct.unpack('!H', buff[host_len + 5: host_len + 7])
self.remaining_buff = buff[host_len + 7:] self.remaining_buff = buff[host_len + 7:]
except Exception: except Exception:
return (None, None, None) return (None, None, None)
return (req_type, host, port) return (req_type, host, port)
def read_connect(self): def read_connect(self):
''' connect responce: version, auth method ''' ''' connect responce: version, auth method '''
buff = self._recv() buff = self._recv()
@ -636,7 +631,7 @@ class Socks5:
version, method = None, None version, method = None, None
if version != 0x05 or method == 0xff: if version != 0x05 or method == 0xff:
self.disconnect() self.disconnect()
def continue_paused_transfer(self): def continue_paused_transfer(self):
if self.state < 5: if self.state < 5:
return return
@ -644,18 +639,20 @@ class Socks5:
self.idlequeue.plug_idle(self, False, True) self.idlequeue.plug_idle(self, False, True)
else: else:
self.idlequeue.plug_idle(self, True, False) self.idlequeue.plug_idle(self, True, False)
def _get_sha1_auth(self): def _get_sha1_auth(self):
''' get sha of sid + Initiator jid + Target jid ''' ''' get sha of sid + Initiator jid + Target jid '''
if 'is_a_proxy' in self.file_props: if 'is_a_proxy' in self.file_props:
del(self.file_props['is_a_proxy']) del(self.file_props['is_a_proxy'])
return sha.new('%s%s%s' % (self.sid, self.file_props['proxy_sender'], return sha.new('%s%s%s' % (self.sid, self.file_props['proxy_sender'],
self.file_props['proxy_receiver'])).hexdigest() self.file_props['proxy_receiver'])).hexdigest()
return sha.new('%s%s%s' % (self.sid, self.initiator, self.target)).hexdigest() return sha.new('%s%s%s' % (self.sid, self.initiator, self.target)).\
hexdigest()
class Socks5Sender(Socks5, IdleObject): class Socks5Sender(Socks5, IdleObject):
''' class for sending file to socket over socks5 ''' ''' class for sending file to socket over socks5 '''
def __init__(self, idlequeue, sock_hash, parent, _sock, host = None, port = None): def __init__(self, idlequeue, sock_hash, parent, _sock, host=None,
port=None):
self.queue_idx = sock_hash self.queue_idx = sock_hash
self.queue = parent self.queue = parent
Socks5.__init__(self, idlequeue, host, port, None, None, None) Socks5.__init__(self, idlequeue, host, port, None, None, None)
@ -669,7 +666,7 @@ class Socks5Sender(Socks5, IdleObject):
self.file_props = None self.file_props = None
# start waiting for data # start waiting for data
self.idlequeue.plug_idle(self, False, True) self.idlequeue.plug_idle(self, False, True)
def read_timeout(self): def read_timeout(self):
self.idlequeue.remove_timeout(self.fd) self.idlequeue.remove_timeout(self.fd)
if self.state > 5: if self.state > 5:
@ -680,9 +677,9 @@ class Socks5Sender(Socks5, IdleObject):
if SEND_TIMEOUT > 0: if SEND_TIMEOUT > 0:
self.idlequeue.set_read_timeout(self.fd, SEND_TIMEOUT) self.idlequeue.set_read_timeout(self.fd, SEND_TIMEOUT)
else: else:
# stop transfer, there is no error code for this # stop transfer, there is no error code for this
self.pollend() self.pollend()
def pollout(self): def pollout(self):
if not self.connected: if not self.connected:
self.disconnect() self.disconnect()
@ -696,7 +693,7 @@ class Socks5Sender(Socks5, IdleObject):
if self.file_props['paused']: if self.file_props['paused']:
self.file_props['continue_cb'] = self.continue_paused_transfer self.file_props['continue_cb'] = self.continue_paused_transfer
self.idlequeue.plug_idle(self, False, False) self.idlequeue.plug_idle(self, False, False)
return return
result = self.write_next() result = self.write_next()
self.queue.process_result(result, self) self.queue.process_result(result, self)
if result is None or result <= 0: if result is None or result <= 0:
@ -712,13 +709,13 @@ class Socks5Sender(Socks5, IdleObject):
self.state += 1 self.state += 1
# unplug and plug this time for reading # unplug and plug this time for reading
self.idlequeue.plug_idle(self, False, True) self.idlequeue.plug_idle(self, False, True)
def pollend(self): def pollend(self):
self.state = 8 # end connection self.state = 8 # end connection
self.disconnect() self.disconnect()
self.file_props['error'] = -1 self.file_props['error'] = -1
self.queue.process_result(-1, self) self.queue.process_result(-1, self)
def pollin(self): def pollin(self):
if self.connected: if self.connected:
if self.state < 5: if self.state < 5:
@ -727,17 +724,16 @@ class Socks5Sender(Socks5, IdleObject):
self.queue.result_sha(self.sha_msg, self.queue_idx) self.queue.result_sha(self.sha_msg, self.queue_idx)
if result == -1: if result == -1:
self.disconnect() self.disconnect()
elif self.state == 5: elif self.state == 5:
if self.file_props is not None and \ if self.file_props is not None and self.file_props['type'] == 'r':
self.file_props['type'] == 'r':
result = self.get_file_contents(0) result = self.get_file_contents(0)
self.queue.process_result(result, self) self.queue.process_result(result, self)
else: else:
self.disconnect() self.disconnect()
def send_file(self): def send_file(self):
''' start sending the file over verified connection ''' ''' start sending the file over verified connection '''
if self.file_props['started']: if self.file_props['started']:
return return
self.file_props['error'] = 0 self.file_props['error'] = 0
@ -756,7 +752,7 @@ class Socks5Sender(Socks5, IdleObject):
# plug for writing # plug for writing
self.idlequeue.plug_idle(self, True, False) self.idlequeue.plug_idle(self, True, False)
return self.write_next() # initial for nl byte return self.write_next() # initial for nl byte
def main(self): def main(self):
''' initial requests for verifying the connection ''' ''' initial requests for verifying the connection '''
if self.state == 1: # initial read if self.state == 1: # initial read
@ -775,8 +771,8 @@ class Socks5Sender(Socks5, IdleObject):
# unplug & plug for writing # unplug & plug for writing
self.idlequeue.plug_idle(self, True, False) self.idlequeue.plug_idle(self, True, False)
return None return None
def disconnect(self, cb = True): def disconnect(self, cb=True):
''' Closes the socket. ''' ''' Closes the socket. '''
# close connection and remove us from the queue # close connection and remove us from the queue
Socks5.disconnect(self) Socks5.disconnect(self)
@ -788,20 +784,20 @@ class Socks5Sender(Socks5, IdleObject):
class Socks5Listener(IdleObject): class Socks5Listener(IdleObject):
def __init__(self, idlequeue, port): def __init__(self, idlequeue, port):
''' handle all incomming connections on (0.0.0.0, port) ''' handle all incomming connections on (0.0.0.0, port)
This class implements IdleObject, but we will expect This class implements IdleObject, but we will expect
only pollin events though only pollin events though
''' '''
self.port = port self.port = port
self.ais = socket.getaddrinfo(None, port, socket.AF_UNSPEC, self.ais = socket.getaddrinfo(None, port, socket.AF_UNSPEC,
socket.SOCK_STREAM, socket.SOL_TCP, socket.AI_PASSIVE) socket.SOCK_STREAM, socket.SOL_TCP, socket.AI_PASSIVE)
self.queue_idx = -1 self.queue_idx = -1
self.idlequeue = idlequeue self.idlequeue = idlequeue
self.queue = None self.queue = None
self.started = False self.started = False
self._sock = None self._sock = None
self.fd = -1 self.fd = -1
def bind(self): def bind(self):
for ai in self.ais: for ai in self.ais:
#try the different possibilities (ipv6, ipv4, etc.) #try the different possibilities (ipv6, ipv4, etc.)
@ -825,16 +821,16 @@ class Socks5Listener(IdleObject):
self.fd = self._serv.fileno() self.fd = self._serv.fileno()
self.idlequeue.plug_idle(self, False, True) self.idlequeue.plug_idle(self, False, True)
self.started = True self.started = True
def pollend(self): def pollend(self):
''' called when we stop listening on (host, port) ''' ''' called when we stop listening on (host, port) '''
self.disconnect() self.disconnect()
def pollin(self): def pollin(self):
''' accept a new incomming connection and notify queue''' ''' accept a new incomming connection and notify queue'''
sock = self.accept_conn() sock = self.accept_conn()
self.queue.on_connection_accepted(sock) self.queue.on_connection_accepted(sock)
def disconnect(self): def disconnect(self):
''' free all resources, we are not listening anymore ''' ''' free all resources, we are not listening anymore '''
self.idlequeue.remove_timeout(self.fd) self.idlequeue.remove_timeout(self.fd)
@ -846,13 +842,13 @@ class Socks5Listener(IdleObject):
self._serv.close() self._serv.close()
except Exception: except Exception:
pass pass
def accept_conn(self): def accept_conn(self):
''' accepts a new incomming connection ''' ''' accepts a new incomming connection '''
_sock = self._serv.accept() _sock = self._serv.accept()
_sock[0].setblocking(False) _sock[0].setblocking(False)
return _sock return _sock
class Socks5Receiver(Socks5, IdleObject): class Socks5Receiver(Socks5, IdleObject):
def __init__(self, idlequeue, streamhost, sid, file_props = None): def __init__(self, idlequeue, streamhost, sid, file_props = None):
self.queue_idx = -1 self.queue_idx = -1
@ -871,9 +867,10 @@ class Socks5Receiver(Socks5, IdleObject):
self.file_props['paused'] = False self.file_props['paused'] = False
self.file_props['continue_cb'] = self.continue_paused_transfer self.file_props['continue_cb'] = self.continue_paused_transfer
self.file_props['stalled'] = False self.file_props['stalled'] = False
Socks5.__init__(self, idlequeue, streamhost['host'], int(streamhost['port']), Socks5.__init__(self, idlequeue, streamhost['host'],
streamhost['initiator'], streamhost['target'], sid) int(streamhost['port']), streamhost['initiator'], streamhost['target'],
sid)
def read_timeout(self): def read_timeout(self):
self.idlequeue.remove_timeout(self.fd) self.idlequeue.remove_timeout(self.fd)
if self.state > 5: if self.state > 5:
@ -886,11 +883,11 @@ class Socks5Receiver(Socks5, IdleObject):
if READ_TIMEOUT > 0: if READ_TIMEOUT > 0:
self.idlequeue.set_read_timeout(self.fd, READ_TIMEOUT) self.idlequeue.set_read_timeout(self.fd, READ_TIMEOUT)
else: else:
# stop transfer, there is no error code for this # stop transfer, there is no error code for this
self.pollend() self.pollend()
else: else:
self.queue.reconnect_receiver(self, self.streamhost) self.queue.reconnect_receiver(self, self.streamhost)
def connect(self): def connect(self):
''' create the socket and plug it to the idlequeue ''' ''' create the socket and plug it to the idlequeue '''
if self.ais is None: if self.ais is None:
@ -898,10 +895,10 @@ class Socks5Receiver(Socks5, IdleObject):
for ai in self.ais: for ai in self.ais:
try: try:
self._sock=socket.socket(*ai[:3]) self._sock = socket.socket(*ai[:3])
# this will not block the GUI # this will not block the GUI
self._sock.setblocking(False) self._sock.setblocking(False)
self._server=ai[4] self._server = ai[4]
break break
except Exception: except Exception:
if sys.exc_value[0] == errno.EINPROGRESS: if sys.exc_value[0] == errno.EINPROGRESS:
@ -914,11 +911,12 @@ class Socks5Receiver(Socks5, IdleObject):
self.do_connect() self.do_connect()
self.idlequeue.set_read_timeout(self.fd, CONNECT_TIMEOUT) self.idlequeue.set_read_timeout(self.fd, CONNECT_TIMEOUT)
return None return None
def _is_connected(self): def _is_connected(self):
if self.state < 5: if self.state < 5:
return False return False
return True return True
def pollout(self): def pollout(self):
self.idlequeue.remove_timeout(self.fd) self.idlequeue.remove_timeout(self.fd)
if self.state == 0: if self.state == 0:
@ -939,7 +937,7 @@ class Socks5Receiver(Socks5, IdleObject):
# unplug and plug for reading # unplug and plug for reading
self.idlequeue.plug_idle(self, False, True) self.idlequeue.plug_idle(self, False, True)
self.idlequeue.set_read_timeout(self.fd, CONNECT_TIMEOUT) self.idlequeue.set_read_timeout(self.fd, CONNECT_TIMEOUT)
def pollend(self): def pollend(self):
if self.state >= 5: if self.state >= 5:
# error during transfer # error during transfer
@ -948,7 +946,7 @@ class Socks5Receiver(Socks5, IdleObject):
self.queue.process_result(-1, self) self.queue.process_result(-1, self)
else: else:
self.queue.reconnect_receiver(self, self.streamhost) self.queue.reconnect_receiver(self, self.streamhost)
def pollin(self): def pollin(self):
self.idlequeue.remove_timeout(self.fd) self.idlequeue.remove_timeout(self.fd)
if self.connected: if self.connected:
@ -965,10 +963,9 @@ class Socks5Receiver(Socks5, IdleObject):
self.idlequeue.set_read_timeout(self.fd, STALLED_TIMEOUT) self.idlequeue.set_read_timeout(self.fd, STALLED_TIMEOUT)
result = self.get_file_contents(0) result = self.get_file_contents(0)
self.queue.process_result(result, self) self.queue.process_result(result, self)
else: else:
self.disconnect() self.disconnect()
def do_connect(self): def do_connect(self):
try: try:
self._sock.connect(self._server) self._sock.connect(self._server)
@ -979,7 +976,7 @@ class Socks5Receiver(Socks5, IdleObject):
(errnum, errstr) = ee (errnum, errstr) = ee
self.connect_timeout += 1 self.connect_timeout += 1
if errnum == 111 or self.connect_timeout > 1000: if errnum == 111 or self.connect_timeout > 1000:
self.queue._connection_refused(self.streamhost, self.queue._connection_refused(self.streamhost,
self.file_props, self.queue_idx) self.file_props, self.queue_idx)
return None return None
# win32 needs this # win32 needs this
@ -994,13 +991,13 @@ class Socks5Receiver(Socks5, IdleObject):
self.file_props['connected'] = True self.file_props['connected'] = True
self.file_props['disconnect_cb'] = self.disconnect self.file_props['disconnect_cb'] = self.disconnect
self.state = 1 # connected self.state = 1 # connected
# stop all others connections to sender's streamhosts # stop all others connections to sender's streamhosts
self.queue._socket_connected(self.streamhost, self.file_props) self.queue._socket_connected(self.streamhost, self.file_props)
self.idlequeue.plug_idle(self, True, False) self.idlequeue.plug_idle(self, True, False)
return 1 # we are connected return 1 # we are connected
def main(self, timeout = 0): def main(self, timeout=0):
''' begin negotiation. on success 'address' != 0 ''' ''' begin negotiation. on success 'address' != 0 '''
result = 1 result = 1
buff = self.receive() buff = self.receive()
@ -1008,7 +1005,7 @@ class Socks5Receiver(Socks5, IdleObject):
# end connection # end connection
self.pollend() self.pollend()
return return
if self.state == 2: # read auth response if self.state == 2: # read auth response
if buff is None or len(buff) != 2: if buff is None or len(buff) != 2:
return None return None
@ -1027,7 +1024,7 @@ class Socks5Receiver(Socks5, IdleObject):
addrlen = ord(buff[4]) addrlen = ord(buff[4])
address = struct.unpack('!%ds' % addrlen, buff[5:addrlen + 5]) address = struct.unpack('!%ds' % addrlen, buff[5:addrlen + 5])
portlen = len(buff[addrlen + 5:]) portlen = len(buff[addrlen + 5:])
if portlen == 1: if portlen == 1:
port, = struct.unpack('!B', buff[addrlen + 5]) port, = struct.unpack('!B', buff[addrlen + 5])
elif portlen == 2: elif portlen == 2:
port, = struct.unpack('!H', buff[addrlen + 5:]) port, = struct.unpack('!H', buff[addrlen + 5:])
@ -1036,14 +1033,14 @@ class Socks5Receiver(Socks5, IdleObject):
self.remaining_buff = buff[addrlen + 7:] self.remaining_buff = buff[addrlen + 7:]
self.state = 5 # for senders: init file_props and send '\n' self.state = 5 # for senders: init file_props and send '\n'
if self.queue.on_success: if self.queue.on_success:
result = self.queue.send_success_reply(self.file_props, result = self.queue.send_success_reply(self.file_props,
self.streamhost) self.streamhost)
if result == 0: if result == 0:
self.state = 8 self.state = 8
self.disconnect() self.disconnect()
# for senders: init file_props # for senders: init file_props
if result == 1 and self.state == 5: if result == 1 and self.state == 5:
if self.file_props['type'] == 's': if self.file_props['type'] == 's':
self.file_props['error'] = 0 self.file_props['error'] = 0
self.file_props['disconnect_cb'] = self.disconnect self.file_props['disconnect_cb'] = self.disconnect
@ -1063,15 +1060,15 @@ class Socks5Receiver(Socks5, IdleObject):
self.idlequeue.plug_idle(self, False, True) self.idlequeue.plug_idle(self, False, True)
self.file_props['continue_cb'] = self.continue_paused_transfer self.file_props['continue_cb'] = self.continue_paused_transfer
# we have set up the connection, next - retrieve file # we have set up the connection, next - retrieve file
self.state = 6 self.state = 6
if self.state < 5: if self.state < 5:
self.idlequeue.plug_idle(self, True, False) self.idlequeue.plug_idle(self, True, False)
self.state += 1 self.state += 1
return None return None
def disconnect(self, cb = True): def disconnect(self, cb=True):
''' Closes the socket. Remove self from queue if cb is True''' ''' Closes the socket. Remove self from queue if cb is True'''
# close connection # close connection
Socks5.disconnect(self) Socks5.disconnect(self)
if cb is True: if cb is True:
self.file_props['disconnect_cb'] = None self.file_props['disconnect_cb'] = None