proper disconnect routines

This commit is contained in:
Dimitur Kirov 2005-08-10 15:59:55 +00:00
parent 8393d9e5fd
commit 73c5eb3dd2
2 changed files with 124 additions and 29 deletions

View File

@ -523,16 +523,27 @@ class Connection:
streamhost = query.getTag('streamhost-used') streamhost = query.getTag('streamhost-used')
except: # this bytestream result is not what we need except: # this bytestream result is not what we need
pass pass
if streamhost is None:
# proxy approves the activate query
raise common.xmpp.NodeProcessed
jid = streamhost.getAttr('jid')
id = real_id[3:] id = real_id[3:]
if self.files_props.has_key(id): if self.files_props.has_key(id):
file_props = self.files_props[id] file_props = self.files_props[id]
else: else:
raise common.xmpp.NodeProcessed raise common.xmpp.NodeProcessed
file_props['type'] if streamhost is None:
# proxy approves the activate query
if real_id[:3] == 'au_':
id = real_id[3:]
if not file_props.has_key('streamhost-used') or \
file_props['streamhost-used'] is False:
raise common.xmpp.NodeProcessed
if not file_props.has_key('proxyhosts'):
raise common.xmpp.NodeProcessed
for host in file_props['proxyhosts']:
if host['initiator'] == frm and \
str(query.getAttr('sid')) == file_props['sid']:
gajim.socks5queue.activate_proxy(host['idx'])
break
raise common.xmpp.NodeProcessed
jid = streamhost.getAttr('jid')
if file_props.has_key('streamhost-used') and \ if file_props.has_key('streamhost-used') and \
file_props['streamhost-used'] is True: file_props['streamhost-used'] is True:
raise common.xmpp.NodeProcessed raise common.xmpp.NodeProcessed
@ -569,6 +580,39 @@ class Connection:
raise common.xmpp.NodeProcessed raise common.xmpp.NodeProcessed
def remove_all_transfers(self):
''' stops and removes all active connections from the socks5 pool '''
for file_props in self.files_props.values():
self.remove_transfer(file_props, remove_from_list = False)
del(self.files_props)
self.files_props = {}
def remove_transfer(self, file_props, remove_from_list = True):
if file_props.has_key('hash'):
gajim.socks5queue.remove_sender(file_props['hash'])
if file_props.has_key('streamhosts'):
for host in file_props['streamhosts']:
if host['idx'] > 0:
gajim.socks5queue.remove_receiver(host['idx'])
gajim.socks5queue.remove_sender(host['idx'])
sid = file_props['sid']
gajim.socks5queue.remove_file_props(self.name, sid)
if remove_from_list:
if self.files_props.has_key('sid'):
del(self.files_props['sid'])
def disconnect_transfer(self, file_props):
if file_props.has_key('hash'):
gajim.socks5queue.remove_sender(file_props['hash'])
if file_props.has_key('streamhosts'):
for host in file_props['streamhosts']:
if host['idx'] > 0:
gajim.socks5queue.remove_receiver(host['idx'])
gajim.socks5queue.remove_sender(host['idx'])
def proxy_auth_ok(self, proxy): def proxy_auth_ok(self, proxy):
'''cb, called after authentication to proxy server ''' '''cb, called after authentication to proxy server '''
file_props = self.files_props[proxy['sid']] file_props = self.files_props[proxy['sid']]
@ -1384,6 +1428,7 @@ class Connection:
p = self.add_sha(p) p = self.add_sha(p)
if msg: if msg:
p.setStatus(msg) p.setStatus(msg)
self.remove_all_transfers()
if self.connection: if self.connection:
self.connection.send(p) self.connection.send(p)
try: try:

View File

@ -35,7 +35,7 @@ class SocksQueue:
self.readers = {} self.readers = {}
self.files_props = {} self.files_props = {}
self.senders = {} self.senders = {}
self.idx = 0 self.idx = 1
self.listener = None self.listener = None
self.sha_handlers = {} self.sha_handlers = {}
self.complete_transfer_cb = complete_transfer_cb self.complete_transfer_cb = complete_transfer_cb
@ -60,16 +60,16 @@ class SocksQueue:
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 True return 2
return False return 0
if file_props.has_key('streamhosts'): if file_props.has_key('streamhosts'):
for host in file_props['streamhosts']: for host in file_props['streamhosts']:
if streamhost['state'] == 1 and host != streamhost: if streamhost['state'] == 1:
return False return 0
streamhost['state'] = 1 streamhost['state'] = 1
self.on_success(streamhost) self.on_success(streamhost)
return True return 1
return False 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):
@ -144,7 +144,29 @@ class SocksQueue:
if self.sha_handlers.has_key(sha_str): if self.sha_handlers.has_key(sha_str):
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):
if not self.readers.has_key(idx):
return
reader = self.readers[idx]
if reader.file_props['type'] != 's':
return
if reader.state != 5:
return
reader.state = 6
if reader.connected:
reader.fd = open(reader.file_props['file-name'])
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['received-len'] = 0
reader.pauses = 0
reader.send_raw(reader._get_nl_byte())
result = reader.write_next()
self.process_result(result, reader)
def send_file(self, file_props, account): def send_file(self, file_props, account):
if file_props.has_key('hash') and \ if file_props.has_key('hash') and \
self.senders.has_key(file_props['hash']): self.senders.has_key(file_props['hash']):
@ -170,6 +192,15 @@ class SocksQueue:
if not self.files_props.has_key(account): if not self.files_props.has_key(account):
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):
if self.files_props.has_key(account):
fl_props = self.files_props[account]
if fl_props.has_key(sid):
del(fl_props[sid])
if len(self.files_props) == 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 '''
@ -240,6 +271,8 @@ class SocksQueue:
if pd: if pd:
result = receiver.main(0) result = receiver.main(0)
self.process_result(result, receiver) self.process_result(result, receiver)
elif receiver.state == 5: # wait for proxy reply
pass
else: else:
if receiver.file_props['type'] == 'r': if receiver.file_props['type'] == 'r':
result = receiver.get_file_contents(timeout) result = receiver.get_file_contents(timeout)
@ -266,23 +299,29 @@ class SocksQueue:
self.progress_transfer_cb(actor.account, self.progress_transfer_cb(actor.account,
actor.file_props) actor.file_props)
def remove_receiver(self, idx): 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 self.readers.has_key(idx): if self.readers.has_key(idx):
if self.readers[idx].streamhost is not None: if do_disconnect:
self.readers[idx].streamhost['state'] = -1 self.readers[idx].disconnect()
del(self.readers[idx]) else:
if self.readers[idx].streamhost is not None:
self.readers[idx].streamhost['state'] = -1
del(self.readers[idx])
def remove_sender(self, idx): def remove_sender(self, idx, do_disconnect = True):
''' Remove reciver from the list of senders and decrease the ''' Remove reciver 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 self.senders.has_key(idx): if self.senders.has_key(idx):
del(self.senders[idx]) if do_disconnect:
if self.connected > 0: self.senders[idx].disconnect()
self.connected -= 1 else:
del(self.senders[idx])
if self.connected > 0:
self.connected -= 1
class Socks5: class Socks5:
def __init__(self, host, port, initiator, target, sid): def __init__(self, host, port, initiator, target, sid):
@ -649,13 +688,16 @@ class Socks5Sender(Socks5):
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
self._sock.close() try:
self._sock.close()
except:
pass
self.connected = False self.connected = False
if self.file_props is not None: if self.file_props is not None:
self.file_props['connected'] = False self.file_props['connected'] = False
self.file_props['disconnect_cb'] = None self.file_props['disconnect_cb'] = None
if self.queue is not None: if self.queue is not None:
self.queue.remove_sender(self.queue_idx) self.queue.remove_sender(self.queue_idx, False)
class Socks5Listener: class Socks5Listener:
def __init__(self, host, port): def __init__(self, host, port):
@ -740,12 +782,14 @@ class Socks5Receiver(Socks5):
self.buff = '' self.buff = ''
self.connected = True self.connected = True
self.file_props['connected'] = True self.file_props['connected'] = True
self.file_props['disconnect_cb'] = self.disconnect
self.state = 1 # connected self.state = 1 # connected
self.queue._socket_connected(self.streamhost, self.file_props) self.queue._socket_connected(self.streamhost, self.file_props)
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
if self.state == 1: # send initially: version and auth types if self.state == 1: # send initially: version and auth types
self.send_raw(self._get_auth_buff()) self.send_raw(self._get_auth_buff())
elif self.state == 2: # read auth response elif self.state == 2: # read auth response
@ -779,11 +823,14 @@ class Socks5Receiver(Socks5):
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:
if not self.queue.send_success_reply(self.file_props, result = self.queue.send_success_reply(self.file_props,
self.streamhost): self.streamhost)
if result == 0:
self.state = 8 self.state = 8
self.disconnect() self.disconnect()
if self.state == 5: # for senders: init file_props and send '\n'
# for senders: init file_props and send '\n'
if result == 1 and self.state == 5:
if self.file_props['type'] == 's': if self.file_props['type'] == 's':
self.fd = open(self.file_props['file-name']) self.fd = open(self.file_props['file-name'])
self.file_props['error'] = 0 self.file_props['error'] = 0
@ -796,7 +843,7 @@ class Socks5Receiver(Socks5):
self.pauses = 0 self.pauses = 0
self.send_raw(self._get_nl_byte()) self.send_raw(self._get_nl_byte())
self.state = 6 # send/get file contents self.state = 6 # send/get file contents
if self.state < 6: if self.state < 5:
self.state += 1 self.state += 1
return None return None
# we have set up the connection, next - retrieve file # we have set up the connection, next - retrieve file
@ -818,9 +865,12 @@ class Socks5Receiver(Socks5):
''' Closes the socket. ''' ''' Closes the socket. '''
# close connection and remove us from the queue # close connection and remove us from the queue
if self._sock: if self._sock:
self._sock.close() try:
self._sock.close()
except:
pass
self.connected = False self.connected = False
if cb is True: if cb is True:
self.file_props['disconnect_cb'] = None self.file_props['disconnect_cb'] = None
if self.queue is not None: if self.queue is not None:
self.queue.remove_receiver(self.queue_idx) self.queue.remove_receiver(self.queue_idx, False)