added proxies65_cache for faster work of FT
set file_transfers_proxy to proxy.jabber.org
This commit is contained in:
parent
680dace366
commit
e8c27c036d
3 changed files with 152 additions and 121 deletions
|
@ -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
|
||||||
|
|
|
@ -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']:
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Reference in a new issue