added proxies65_cache for faster work of FT

set file_transfers_proxy to proxy.jabber.org
This commit is contained in:
Dimitur Kirov 2005-08-06 20:18:44 +00:00
parent 680dace366
commit e8c27c036d
3 changed files with 152 additions and 121 deletions

View file

@ -158,6 +158,7 @@ class Config:
'try_connecting_for_foo_secs': [ opt_int, 60 ], 'try_connecting_for_foo_secs': [ opt_int, 60 ],
'max_stanza_per_sec': [ opt_int, 5], 'max_stanza_per_sec': [ opt_int, 5],
'http_auth': [opt_str, 'ask'], # yes, no, ask 'http_auth': [opt_str, 'ask'], # yes, no, ask
'file_transfers_proxy': [opt_str, 'proxy.jabber.org'] # proxy65 for FT
}, {}), }, {}),
'statusmsg': ({ 'statusmsg': ({
'message': [ opt_str, '' ], 'message': [ opt_str, '' ],
@ -176,6 +177,11 @@ class Config:
'user': [ opt_str, '' ], 'user': [ opt_str, '' ],
'pass': [ opt_str, '' ], 'pass': [ opt_str, '' ],
}, {}), }, {}),
'proxies65_cache': ({
'host': [ opt_str, ''],
'port': [ opt_str, '7777'],
'jid': [ opt_str, ''],
}, {}),
'themes': ({ 'themes': ({
'accounttextcolor': [ opt_color, '' ], 'accounttextcolor': [ opt_color, '' ],
'accountbgcolor': [ opt_color, '' ], 'accountbgcolor': [ opt_color, '' ],
@ -285,6 +291,10 @@ class Config:
'#996442' ], '#996442' ],
} }
proxies65_default = {
'proxy.jabber.org': [ '208.245.212.98', '7777', 'proxy.jabber.org' ],
}
def foreach(self, cb, data = None): def foreach(self, cb, data = None):
for opt in self.__options: for opt in self.__options:
cb(data, opt, None, self.__options[opt]) cb(data, opt, None, self.__options[opt])
@ -414,4 +424,12 @@ class Config:
self.add_per('soundevents', event) self.add_per('soundevents', event)
self.set_per('soundevents', event, 'enabled', default[0]) self.set_per('soundevents', event, 'enabled', default[0])
self.set_per('soundevents', event, 'path', default[1]) self.set_per('soundevents', event, 'path', default[1])
# set initial cache values for proxie65 hosts
for proxy in self.proxies65_default:
default = self.proxies65_default[proxy]
self.add_per('proxies65_cache', proxy)
self.set_per('proxies65_cache', proxy, 'host', default[0])
self.set_per('proxies65_cache', proxy, 'port', default[1])
self.set_per('proxies65_cache', proxy, 'jid', default[2])
return return

View file

@ -387,8 +387,6 @@ class Connection:
id = str(iq_obj.getAttr('id')) id = str(iq_obj.getAttr('id'))
query = iq_obj.getTag('query') query = iq_obj.getTag('query')
streamhost = query.getTag('streamhost') streamhost = query.getTag('streamhost')
host = streamhost.getAttr('host')
port = streamhost.getAttr('port')
jid = iq_obj.getFrom().getStripped().encode('utf8') jid = iq_obj.getFrom().getStripped().encode('utf8')
id = id[3:] id = id[3:]
if not self.files_props.has_key(id): if not self.files_props.has_key(id):
@ -409,10 +407,10 @@ class Connection:
for item in query.getChildren(): for item in query.getChildren():
if item.getName() == 'streamhost': if item.getName() == 'streamhost':
host_dict={ host_dict={
'state' : 0, 'state': 0,
'target' : target, 'target': target,
'id' : id, 'id': id,
'initiator' : str(iq_obj.getFrom()) 'initiator': str(iq_obj.getFrom())
} }
for attr in item.getAttrs(): for attr in item.getAttrs():
val = item.getAttr(attr) val = item.getAttr(attr)
@ -426,13 +424,6 @@ class Connection:
if self.files_props.has_key(sid): if self.files_props.has_key(sid):
file_props = self.files_props[sid] file_props = self.files_props[sid]
file_props['fast'] = streamhosts file_props['fast'] = streamhosts
# this is not good, but the only way to work with psi!
if len(gajim.socks5queue.readers) == 0 and \
len(gajim.socks5queue.senders) == 0:
self._connect_error(str(iq_obj.getFrom()), id, code = 406)
# END not good
raise common.xmpp.NodeProcessed raise common.xmpp.NodeProcessed
fast = None fast = None
try: try:
@ -440,8 +431,8 @@ class Connection:
except Exception, e: except Exception, e:
pass pass
if fast is not None: if fast is not None:
if fast.getNamespace() == 'http://affinix.com/jabber/stream': if fast.getNamespace() == common.xmpp.NS_STREAM:
self.send_socks5_info(file_props, fast = False, \ self.send_socks5_info(file_props, fast = False,
receiver = file_props['sender'], sender = file_props['receiver']) receiver = file_props['sender'], sender = file_props['receiver'])
self.files_props[sid] = file_props self.files_props[sid] = file_props
file_props['streamhosts'] = streamhosts file_props['streamhosts'] = streamhosts
@ -457,7 +448,7 @@ class Connection:
''' '''
if streamhost is None: if streamhost is None:
return None return None
iq = common.xmpp.Iq(to = streamhost['initiator'], typ = 'result', \ iq = common.xmpp.Iq(to = streamhost['initiator'], typ = 'result',
frm = streamhost['target']) frm = streamhost['target'])
iq.setAttr('id', streamhost['id']) iq.setAttr('id', streamhost['id'])
query = iq.setTag('query') query = iq.setTag('query')
@ -468,9 +459,9 @@ class Connection:
def _connect_error(self, to, id, code = 404): def _connect_error(self, to, id, code = 404):
msg_dict = { msg_dict = {
404 : 'Could not connect to given hosts', 404: 'Could not connect to given hosts',
405 : 'Cancel', 405: 'Cancel',
406 : 'Not acceptable', 406: 'Not acceptable',
} }
msg = msg_dict[code] msg = msg_dict[code]
iq = None iq = None
@ -487,63 +478,49 @@ class Connection:
frm = str(iq_obj.getFrom()) frm = str(iq_obj.getFrom())
real_id = str(iq_obj.getAttr('id')) real_id = str(iq_obj.getAttr('id'))
query = iq_obj.getTag('query') query = iq_obj.getTag('query')
id = real_id[3:] streamhost = None
if not self.files_props.has_key(id): try:
file_props = gajim.socks5queue.get_file_props( streamhost = query.getTag('streamhost')
self.name, id) except:
gajim.socks5queue.get_file_from_sender(file_props, self.name) pass
raise common.xmpp.NodeProcessed if streamhost is not None: # this is a result for proxy request
file_props = self.files_props[id] jid = streamhost.getAttr('jid')
if real_id[:3] == 'au_':
gajim.socks5queue.send_file(file_props, self.name)
raise common.xmpp.NodeProcessed
elif real_id[:3] == 'px_':
proxyhosts = [] proxyhosts = []
for item in query.getChildren(): for item in query.getChildren():
if item.getName() == 'streamhost': if item.getName() == 'streamhost':
host_dict={ host = item.getAttr('host')
'state' : 0, port = item.getAttr('port')
'target' : str(iq_obj.getAttr('to')), jid = item.getAttr('jid')
'id' : id, conf = gajim.config
'initiator' : str(iq_obj.getFrom()) conf.add_per('proxies65_cache', jid)
} conf.set_per('proxies65_cache', jid, 'host', str(host))
for attr in item.getAttrs(): conf.set_per('proxies65_cache', jid, 'port', int(port))
val = item.getAttr(attr) conf.set_per('proxies65_cache', jid, 'jid', str(jid))
host_dict[str(attr)] = str(val) raise common.xmpp.NodeProcessed
proxyhosts.append(host_dict) try:
file_props['proxyhosts'] = proxyhosts streamhost = query.getTag('streamhost-used')
iq = common.xmpp.Protocol(name = 'iq', to = \ except: # this bytestream result is not what we need
str(file_props['proxy_receiver']), typ = 'set')
port = gajim.config.get('file_transfers_port')
file_props['request-id'] = 'id_' + file_props['sid']
iq.setID(file_props['request-id'])
query = iq.setTag('query')
query.setNamespace(common.xmpp.NS_BYTESTREAM)
query.setAttr('mode', 'tcp')
query.setAttr('sid', file_props['sid'])
streamhost = query.setTag('streamhost')
streamhost.setAttr('port', str(port))
streamhost.setAttr('host', self.peerhost[0])
streamhost.setAttr('jid', str(file_props['proxy_sender']))
for proxyhost in proxyhosts:
streamhost = common.xmpp.Node(tag = 'streamhost')
query.addChild(node=streamhost)
streamhost.setAttr('port', proxyhost['port'])
streamhost.setAttr('host', proxyhost['host'])
streamhost.setAttr('jid', proxyhost['jid'])
proxy = streamhost.setTag('proxy')
proxy.setNamespace(common.xmpp.NS_STREAM)
fast_tag = query.setTag('fast')
fast_tag.setNamespace(common.xmpp.NS_STREAM)
self.to_be_sent.append(iq)
raise common.xmpp.NodeProcessed raise common.xmpp.NodeProcessed
streamhost = query.getTag('streamhost-used')
jid = streamhost.getAttr('jid') jid = streamhost.getAttr('jid')
id = real_id[3:]
if not self.files_props.has_key(id):
file_props = gajim.socks5queue.get_file_props(self.name, id)
gajim.socks5queue.get_file_from_sender(file_props, self.name)
raise common.xmpp.NodeProcessed
file_props = None
if self.files_props.has_key(id):
file_props = self.files_props[id]
else:
raise common.xmpp.NodeProcessed
proxy = None proxy = None
if file_props.has_key('proxyhosts'): if file_props.has_key('proxyhosts'):
for proxyhost in file_props['proxyhosts']: for proxyhost in file_props['proxyhosts']:
if proxyhost['jid'] == jid: if proxyhost['jid'] == jid:
proxy = proxyhost proxy = proxyhost
if real_id[:3] == 'au_':
gajim.socks5queue.send_file(file_props, self.name)
raise common.xmpp.NodeProcessed
if proxy != None: if proxy != None:
if not file_props.has_key('streamhosts'): if not file_props.has_key('streamhosts'):
file_props['streamhosts'] =[] file_props['streamhosts'] =[]
@ -563,6 +540,7 @@ class Connection:
if len(fasts) > 0: if len(fasts) > 0:
self._connect_error(str(iq_obj.getFrom()), fasts[0]['id'], self._connect_error(str(iq_obj.getFrom()), fasts[0]['id'],
code = 406) code = 406)
raise common.xmpp.NodeProcessed raise common.xmpp.NodeProcessed
def proxy_auth_ok(self, proxy): def proxy_auth_ok(self, proxy):
@ -641,39 +619,65 @@ class Connection:
file_props['hash'] = hash_id file_props['hash'] = hash_id
return return
def get_cached_proxies(self, proxy):
''' get cached entries for proxy and request the cache again '''
host = gajim.config.get_per('proxies65_cache', proxy, 'host')
port = gajim.config.get_per('proxies65_cache', proxy, 'port')
jid = gajim.config.get_per('proxies65_cache', proxy, 'jid')
iq = common.xmpp.Protocol(name = 'iq', to = proxy, typ = 'get')
query = iq.setTag('query')
query.setNamespace(common.xmpp.NS_BYTESTREAM)
self.to_be_sent.append(iq)
# ensure that we don;t return empty vars
if None not in (host, port, jid) or '' not in (host, port, jid):
return (host, port, jid)
return (None, None, None)
def send_socks5_info(self, file_props, fast = True, receiver = None, def send_socks5_info(self, file_props, fast = True, receiver = None,
sender = None): sender = None):
''' send iq for the present streamhosts and proxies '''
if type(self.peerhost) != tuple: if type(self.peerhost) != tuple:
return return
port = gajim.config.get('file_transfers_port') port = gajim.config.get('file_transfers_port')
proxy = gajim.config.get_per('accounts', self.name, 'file_transfers_proxy') proxy = gajim.config.get_per('accounts', self.name, 'file_transfers_proxy')
#~ proxy = 'proxy.jabber.org'
if receiver is None: if receiver is None:
receiver = file_props['receiver'] receiver = file_props['receiver']
if sender is None: if sender is None:
sender = file_props['sender'] sender = file_props['sender']
proxyhosts = []
if proxy:
proxies = map(lambda e:e.strip(), proxy.split(','))
for proxy in proxies:
(host, _port, jid) = self.get_cached_proxies(proxy)
if host is None:
continue
host_dict={
'state': 0,
'target': str(receiver),
'id': id,
'initiator': proxy,
'host': host,
'port': str(_port),
'jid': jid
}
proxyhosts.append(host_dict)
sha_str = self._get_sha(file_props['sid'], sender, sha_str = self._get_sha(file_props['sid'], sender,
receiver) receiver)
file_props['sha_str'] = sha_str file_props['sha_str'] = sha_str
listener = gajim.socks5queue.start_listener(self.peerhost[0], port, listener = gajim.socks5queue.start_listener(self.peerhost[0], port,
sha_str, self.result_socks5_sid, file_props['sid']) sha_str, self.result_socks5_sid, file_props['sid'])
if listener == None: if listener == None:
if streamhost == []:
file_props['error'] = -3
self.dispatch('FILE_REQUEST_ERROR', (jid, file_props))
print ''
# FIXME - raise error dialog that address is in use # FIXME - raise error dialog that address is in use
return return
if proxy:
iq = common.xmpp.Protocol(name = 'iq', to = str(proxy),
typ = 'get')
proxy_id = 'px_' + file_props['sid']
iq.setID(proxy_id)
query = iq.setTag('query')
query.setNamespace(common.xmpp.NS_BYTESTREAM)
self.to_be_sent.append(iq)
file_props['proxy_receiver'] = str(receiver)
file_props['proxy_sender'] = str(sender)
return
iq = common.xmpp.Protocol(name = 'iq', to = str(receiver), iq = common.xmpp.Protocol(name = 'iq', to = str(receiver),
typ = 'set') typ = 'set')
file_props['request-id'] = 'id_' + file_props['sid'] file_props['request-id'] = 'id_' + file_props['sid']
@ -686,11 +690,21 @@ class Connection:
streamhost.setAttr('port', str(port)) streamhost.setAttr('port', str(port))
streamhost.setAttr('host', self.peerhost[0]) streamhost.setAttr('host', self.peerhost[0])
streamhost.setAttr('jid', sender) streamhost.setAttr('jid', sender)
if proxyhosts != []:
file_props['proxy_receiver'] = str(receiver)
file_props['proxy_sender'] = str(sender)
file_props['proxyhosts'] = proxyhosts
for proxyhost in proxyhosts:
streamhost = common.xmpp.Node(tag = 'streamhost')
query.addChild(node=streamhost)
streamhost.setAttr('port', proxyhost['port'])
streamhost.setAttr('host', proxyhost['host'])
streamhost.setAttr('jid', proxyhost['jid'])
proxy = streamhost.setTag('proxy')
proxy.setNamespace(common.xmpp.NS_STREAM)
if fast: if fast:
fast_tag = query.setTag('fast') fast_tag = query.setTag('fast')
fast_tag.setNamespace(common.xmpp.NS_STREAM) fast_tag.setNamespace(common.xmpp.NS_STREAM)
self.to_be_sent.append(iq) self.to_be_sent.append(iq)
def _siSetCB(self, con, iq_obj): def _siSetCB(self, con, iq_obj):
@ -703,7 +717,7 @@ class Connection:
return return
feature = si.getTag('feature') feature = si.getTag('feature')
file_tag = si.getTag('file') file_tag = si.getTag('file')
file_props = {'type' : 'r'} file_props = {'type': 'r'}
for attribute in file_tag.getAttrs(): for attribute in file_tag.getAttrs():
attribute = attribute.encode('utf-8') attribute = attribute.encode('utf-8')
if attribute in ['name', 'size', 'hash', 'date']: if attribute in ['name', 'size', 'hash', 'date']:

View file

@ -22,10 +22,6 @@
import socket import socket
import select import select
import os import os
try:
import fcntl
except:
pass
import struct import struct
import sha import sha
@ -33,7 +29,7 @@ MAX_BUFF_LEN = 65536
class SocksQueue: class SocksQueue:
''' queue for all file requests objects ''' ''' queue for all file requests objects '''
def __init__(self, complete_transfer_cb = None, \ def __init__(self, complete_transfer_cb = None,
progress_transfer_cb = None): progress_transfer_cb = None):
self.connected = 0 self.connected = 0
self.readers = {} self.readers = {}
@ -62,6 +58,7 @@ class SocksQueue:
self.on_success = on_success self.on_success = on_success
self.on_failure = on_failure self.on_failure = on_failure
if not self.files_props.has_key(account): if not self.files_props.has_key(account):
print '\n\nFIXME '
pass pass
# FIXME ---- show error dialog # FIXME ---- show error dialog
else: else:
@ -87,7 +84,7 @@ class SocksQueue:
self.remove_receiver(idx) self.remove_receiver(idx)
if file_props['failure_cb']: if file_props['failure_cb']:
file_props['failure_cb'](streamhost['initiator'], streamhost['id'], file_props['failure_cb'](streamhost['initiator'], streamhost['id'],
code = 404) code = 404)
else: else:
# show error dialog, it seems to be the laast try # show error dialog, it seems to be the laast try
pass pass
@ -109,6 +106,9 @@ class SocksQueue:
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:
return
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']):
sender = self.senders[file_props['hash']] sender = self.senders[file_props['hash']]
@ -344,7 +344,7 @@ class Socks5:
except Exception, e: except Exception, e:
if e.args[0] != 11: if e.args[0] != 11:
# peer stopped reading # peer stopped reading
self.state = 8 self.state = 8 # end connection
self.fd.close() self.fd.close()
self.disconnect() self.disconnect()
self.file_props['error'] = -1 self.file_props['error'] = -1
@ -352,7 +352,7 @@ class Socks5:
self.size += lenn self.size += lenn
self.file_props['received-len'] = self.size self.file_props['received-len'] = self.size
if self.size == int(self.file_props['size']): if self.size == int(self.file_props['size']):
self.state = 8 self.state = 8 # end connection
self.file_props['error'] = 0 self.file_props['error'] = 0
self.fd.close() self.fd.close()
self.disconnect() self.disconnect()
@ -369,12 +369,12 @@ class Socks5:
self.file_props['stalled'] = True self.file_props['stalled'] = True
else: else:
self.file_props['stalled'] = False self.file_props['stalled'] = False
self.state = 7 self.state = 7 # continue to write in the socket
if lenn == 0 and self.file_props['stalled'] is False: if lenn == 0 and self.file_props['stalled'] is False:
return None return None
return lenn return lenn
else: else:
self.state = 8 self.state = 8 # end connection
self.disconnect() self.disconnect()
return -1 return -1
@ -497,15 +497,15 @@ class Socks5:
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
@ -531,7 +531,7 @@ class Socks5:
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: except:
return (None, None, None) return (None, None, None)
@ -550,8 +550,7 @@ class Socks5:
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 self.file_props.has_key('is_a_proxy'): if self.file_props.has_key('is_a_proxy'):
return sha.new('%s%s%s' % (self.sid, \ return sha.new('%s%s%s' % (self.sid, self.file_props['proxy_sender'],
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()
@ -585,21 +584,21 @@ class Socks5Sender(Socks5):
def main(self): def main(self):
''' initial requests for verifying the connection ''' ''' initial requests for verifying the connection '''
if self.state == 1: if self.state == 1: # initial read
buff = self.receive() buff = self.receive()
if not self.connected: if not self.connected:
return -1 return -1
mechs = self._parse_auth_buff(buff) mechs = self._parse_auth_buff(buff)
if mechs is None: if mechs is None:
return -1 # invalid auth methods received return -1 # invalid auth methods received
elif self.state == 2: elif self.state == 2: # send reply with desired auth type
self.send_raw(self._get_auth_response()) self.send_raw(self._get_auth_response())
elif self.state == 3: elif self.state == 3: # get next request
buff = self.receive() buff = self.receive()
(req_type, self.sha_msg, port) = self._parse_request_buff(buff) (req_type, self.sha_msg, port) = self._parse_request_buff(buff)
if req_type != 0x01: if req_type != 0x01:
return -1 # request is not of type 'connect' return -1 # request is not of type 'connect'
elif self.state == 4: elif self.state == 4: # send positive response to the 'connect'
self.send_raw(self._get_request_buff(self.sha_msg, 0x00)) self.send_raw(self._get_request_buff(self.sha_msg, 0x00))
self.state += 1 # go to the next step self.state += 1 # go to the next step
return None return None
@ -609,9 +608,9 @@ class Socks5Sender(Socks5):
if self._sock is None: if self._sock is None:
return False return False
try: try:
if self.state in [1, 3, 5]: if self.state in [1, 3, 5]: # (initial, request, send file)
return self.pending_read(timeout) return self.pending_read(timeout)
elif self.state in [2, 4]: elif self.state in [2, 4]: # send auth and positive response
return True return True
except Exception, e: except Exception, e:
return False return False
@ -628,7 +627,6 @@ class Socks5Sender(Socks5):
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)
class Socks5Listener: class Socks5Listener:
def __init__(self, host, port): def __init__(self, host, port):
self.host, self.port = host, port self.host, self.port = host, port
@ -646,7 +644,8 @@ class Socks5Listener:
self._serv.bind(('0.0.0.0', self.port)) self._serv.bind(('0.0.0.0', self.port))
self._serv.listen(socket.SOMAXCONN) self._serv.listen(socket.SOMAXCONN)
self._serv.setblocking(False) self._serv.setblocking(False)
except Exception, (errno, errstr): except Exception, e:
# unable to bind, show error dialog
return None return None
self.started = True self.started = True
@ -713,22 +712,22 @@ class Socks5Receiver(Socks5):
self.file_props['connected'] = True self.file_props['connected'] = True
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 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 '''
if self.state == 1: 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: elif self.state == 2: # read auth response
buff = self.receive() buff = self.receive()
if buff is None or len(buff) != 2: if buff is None or len(buff) != 2:
return None return None
version, method = struct.unpack('!BB', buff[:2]) version, method = struct.unpack('!BB', buff[:2])
if version != 0x05 or method == 0xff: if version != 0x05 or method == 0xff:
self.disconnect() self.disconnect()
elif self.state == 3: elif self.state == 3: # send 'connect' request
self.send_raw(self._get_request_buff(self._get_sha1_auth())) self.send_raw(self._get_request_buff(self._get_sha1_auth()))
elif self.state == 4: elif self.state == 4: # get approve of our request
buff = self.receive() buff = self.receive()
if buff == None: if buff == None:
return None return None
@ -741,17 +740,17 @@ class Socks5Receiver(Socks5):
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: # Gaim bug :) 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:])
else: else: # Gaim bug :)
port, = struct.unpack('!H', buff[addrlen + 5:addrlen + 7]) port, = struct.unpack('!H', buff[addrlen + 5:addrlen + 7])
self.remaining_buff = buff[addrlen + 7:] self.remaining_buff = buff[addrlen + 7:]
self.state = 5 self.state = 5 # for senders: init file_props and send '\n'
if self.queue.on_success: if self.queue.on_success:
self.queue.on_success(self.streamhost) self.queue.on_success(self.streamhost)
if self.state == 5: if self.state == 5: # for senders: init file_props and send '\n'
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
@ -763,20 +762,20 @@ class Socks5Receiver(Socks5):
self.file_props['received-len'] = 0 self.file_props['received-len'] = 0
self.pauses = 0 self.pauses = 0
self.send_raw(self._get_nl_byte()) self.send_raw(self._get_nl_byte())
self.state = 6 self.state = 6 # send/get file contents
if self.state < 6: if self.state < 6:
self.state += 1 self.state += 1
return None return None
# we have set the connection set up, next - retrieve file # we have set up the connection, next - retrieve file
def pending_data(self, timeout=0): def pending_data(self, timeout=0):
''' Returns true if there is a data ready to be read. ''', self.state ''' Returns true if there is a data ready to be read. '''
if self._sock is None: if self._sock is None:
return False return False
try: try:
if self.state in [2, 4, 6]: if self.state in [2, 4, 6]: # auth response, connect, file data
return self.pending_read(0.01) return self.pending_read(0.01)
elif self.state in [1, 3, 5]: elif self.state in [1, 3, 5]: # auth types, connect request
return True return True
except Exception, e: except Exception, e:
return False return False