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 ],
 | 
			
		||||
			'max_stanza_per_sec': [ opt_int, 5],
 | 
			
		||||
			'http_auth': [opt_str, 'ask'], # yes, no, ask
 | 
			
		||||
			'file_transfers_proxy': [opt_str, 'proxy.jabber.org'] # proxy65 for FT
 | 
			
		||||
		}, {}),
 | 
			
		||||
		'statusmsg': ({
 | 
			
		||||
			'message': [ opt_str, '' ],
 | 
			
		||||
| 
						 | 
				
			
			@ -176,6 +177,11 @@ class Config:
 | 
			
		|||
			'user': [ opt_str, '' ],
 | 
			
		||||
			'pass': [ opt_str, '' ],
 | 
			
		||||
		}, {}),
 | 
			
		||||
		'proxies65_cache': ({
 | 
			
		||||
			'host': [ opt_str, ''],
 | 
			
		||||
			'port': [ opt_str, '7777'],
 | 
			
		||||
			'jid': [ opt_str, ''],
 | 
			
		||||
		}, {}),
 | 
			
		||||
		'themes': ({
 | 
			
		||||
			'accounttextcolor': [ opt_color, '' ],
 | 
			
		||||
			'accountbgcolor': [ opt_color, '' ],
 | 
			
		||||
| 
						 | 
				
			
			@ -285,6 +291,10 @@ class Config:
 | 
			
		|||
					'#996442' ],
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	proxies65_default = {
 | 
			
		||||
		'proxy.jabber.org': [ '208.245.212.98', '7777', 'proxy.jabber.org' ],
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	def foreach(self, cb, data = None):
 | 
			
		||||
		for opt in self.__options:
 | 
			
		||||
			cb(data, opt, None, self.__options[opt])
 | 
			
		||||
| 
						 | 
				
			
			@ -414,4 +424,12 @@ class Config:
 | 
			
		|||
			self.add_per('soundevents', event)
 | 
			
		||||
			self.set_per('soundevents', event, 'enabled', default[0])
 | 
			
		||||
			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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -387,8 +387,6 @@ class Connection:
 | 
			
		|||
		id = str(iq_obj.getAttr('id'))
 | 
			
		||||
		query = iq_obj.getTag('query')
 | 
			
		||||
		streamhost =  query.getTag('streamhost')
 | 
			
		||||
		host = streamhost.getAttr('host')
 | 
			
		||||
		port = streamhost.getAttr('port')
 | 
			
		||||
		jid = iq_obj.getFrom().getStripped().encode('utf8')
 | 
			
		||||
		id = id[3:]
 | 
			
		||||
		if not self.files_props.has_key(id):
 | 
			
		||||
| 
						 | 
				
			
			@ -409,10 +407,10 @@ class Connection:
 | 
			
		|||
		for item in query.getChildren():
 | 
			
		||||
			if item.getName() == 'streamhost':
 | 
			
		||||
				host_dict={
 | 
			
		||||
					'state' : 0, 
 | 
			
		||||
					'target' : target, 
 | 
			
		||||
					'id' : id, 
 | 
			
		||||
					'initiator' : str(iq_obj.getFrom())
 | 
			
		||||
					'state': 0, 
 | 
			
		||||
					'target': target, 
 | 
			
		||||
					'id': id, 
 | 
			
		||||
					'initiator': str(iq_obj.getFrom())
 | 
			
		||||
				}
 | 
			
		||||
				for attr in item.getAttrs():
 | 
			
		||||
					val = item.getAttr(attr)
 | 
			
		||||
| 
						 | 
				
			
			@ -426,13 +424,6 @@ class Connection:
 | 
			
		|||
			if self.files_props.has_key(sid):
 | 
			
		||||
				file_props = self.files_props[sid]
 | 
			
		||||
				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
 | 
			
		||||
		fast = None
 | 
			
		||||
		try:
 | 
			
		||||
| 
						 | 
				
			
			@ -440,8 +431,8 @@ class Connection:
 | 
			
		|||
		except Exception, e:
 | 
			
		||||
			pass
 | 
			
		||||
		if fast is not None:
 | 
			
		||||
			if fast.getNamespace() == 'http://affinix.com/jabber/stream':
 | 
			
		||||
				self.send_socks5_info(file_props, fast = False, \
 | 
			
		||||
			if fast.getNamespace() == common.xmpp.NS_STREAM:
 | 
			
		||||
				self.send_socks5_info(file_props, fast = False, 
 | 
			
		||||
				receiver = file_props['sender'], sender = file_props['receiver'])
 | 
			
		||||
				self.files_props[sid] = file_props
 | 
			
		||||
		file_props['streamhosts'] = streamhosts
 | 
			
		||||
| 
						 | 
				
			
			@ -457,7 +448,7 @@ class Connection:
 | 
			
		|||
		'''
 | 
			
		||||
		if streamhost is None:
 | 
			
		||||
			return None
 | 
			
		||||
		iq = common.xmpp.Iq(to = streamhost['initiator'], typ = 'result', \
 | 
			
		||||
		iq = common.xmpp.Iq(to = streamhost['initiator'], typ = 'result', 
 | 
			
		||||
			frm = streamhost['target'])
 | 
			
		||||
		iq.setAttr('id', streamhost['id'])
 | 
			
		||||
		query = iq.setTag('query')
 | 
			
		||||
| 
						 | 
				
			
			@ -468,9 +459,9 @@ class Connection:
 | 
			
		|||
	
 | 
			
		||||
	def _connect_error(self, to, id, code = 404):
 | 
			
		||||
		msg_dict = {
 | 
			
		||||
			404 : 'Could not connect to given hosts', 
 | 
			
		||||
			405 : 'Cancel', 
 | 
			
		||||
			406 : 'Not acceptable', 
 | 
			
		||||
			404: 'Could not connect to given hosts', 
 | 
			
		||||
			405: 'Cancel', 
 | 
			
		||||
			406: 'Not acceptable', 
 | 
			
		||||
		}
 | 
			
		||||
		msg = msg_dict[code]
 | 
			
		||||
		iq = None
 | 
			
		||||
| 
						 | 
				
			
			@ -487,63 +478,49 @@ class Connection:
 | 
			
		|||
		frm = str(iq_obj.getFrom())
 | 
			
		||||
		real_id = str(iq_obj.getAttr('id'))
 | 
			
		||||
		query = iq_obj.getTag('query')
 | 
			
		||||
		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 = self.files_props[id]
 | 
			
		||||
		if real_id[:3] == 'au_':
 | 
			
		||||
			gajim.socks5queue.send_file(file_props, self.name)
 | 
			
		||||
			raise common.xmpp.NodeProcessed
 | 
			
		||||
		elif real_id[:3] == 'px_':
 | 
			
		||||
		streamhost = None
 | 
			
		||||
		try:
 | 
			
		||||
			streamhost = query.getTag('streamhost')
 | 
			
		||||
		except: 
 | 
			
		||||
			pass
 | 
			
		||||
		if streamhost is not None: # this is a result for proxy request
 | 
			
		||||
			jid = streamhost.getAttr('jid')
 | 
			
		||||
			proxyhosts = []
 | 
			
		||||
			for item in query.getChildren():
 | 
			
		||||
				if item.getName() == 'streamhost':
 | 
			
		||||
					host_dict={
 | 
			
		||||
						'state' : 0, 
 | 
			
		||||
						'target' : str(iq_obj.getAttr('to')), 
 | 
			
		||||
						'id' : id, 
 | 
			
		||||
						'initiator' : str(iq_obj.getFrom())
 | 
			
		||||
					}
 | 
			
		||||
					for attr in item.getAttrs():
 | 
			
		||||
						val = item.getAttr(attr)
 | 
			
		||||
						host_dict[str(attr)] = str(val)
 | 
			
		||||
					proxyhosts.append(host_dict)
 | 
			
		||||
			file_props['proxyhosts'] = proxyhosts
 | 
			
		||||
			iq = common.xmpp.Protocol(name = 'iq', to = \
 | 
			
		||||
				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)
 | 
			
		||||
					host = item.getAttr('host')
 | 
			
		||||
					port = item.getAttr('port')
 | 
			
		||||
					jid = item.getAttr('jid')
 | 
			
		||||
					conf = gajim.config
 | 
			
		||||
					conf.add_per('proxies65_cache', jid)
 | 
			
		||||
					conf.set_per('proxies65_cache', jid, 'host', str(host))
 | 
			
		||||
					conf.set_per('proxies65_cache', jid, 'port', int(port))
 | 
			
		||||
					conf.set_per('proxies65_cache', jid, 'jid', str(jid))
 | 
			
		||||
			raise common.xmpp.NodeProcessed
 | 
			
		||||
		try:
 | 
			
		||||
			streamhost =  query.getTag('streamhost-used')
 | 
			
		||||
		except: # this bytestream result is not what we need
 | 
			
		||||
			raise common.xmpp.NodeProcessed
 | 
			
		||||
		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
 | 
			
		||||
		if file_props.has_key('proxyhosts'):
 | 
			
		||||
			for proxyhost in file_props['proxyhosts']:
 | 
			
		||||
				if proxyhost['jid'] == jid:
 | 
			
		||||
					proxy = proxyhost
 | 
			
		||||
		if real_id[:3] == 'au_':
 | 
			
		||||
			gajim.socks5queue.send_file(file_props, self.name)
 | 
			
		||||
			raise common.xmpp.NodeProcessed
 | 
			
		||||
		
 | 
			
		||||
		if proxy != None:
 | 
			
		||||
			if not file_props.has_key('streamhosts'):
 | 
			
		||||
				file_props['streamhosts'] =[]
 | 
			
		||||
| 
						 | 
				
			
			@ -563,6 +540,7 @@ class Connection:
 | 
			
		|||
				if len(fasts) > 0:
 | 
			
		||||
					self._connect_error(str(iq_obj.getFrom()), fasts[0]['id'], 
 | 
			
		||||
						code = 406)
 | 
			
		||||
		
 | 
			
		||||
		raise common.xmpp.NodeProcessed
 | 
			
		||||
	
 | 
			
		||||
	def proxy_auth_ok(self, proxy):
 | 
			
		||||
| 
						 | 
				
			
			@ -641,39 +619,65 @@ class Connection:
 | 
			
		|||
		file_props['hash'] = hash_id
 | 
			
		||||
		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, 
 | 
			
		||||
		sender = None):
 | 
			
		||||
		''' send iq for the present streamhosts and proxies '''
 | 
			
		||||
		if type(self.peerhost) != tuple:
 | 
			
		||||
			return
 | 
			
		||||
		port = gajim.config.get('file_transfers_port')
 | 
			
		||||
		proxy = gajim.config.get_per('accounts', self.name, 'file_transfers_proxy')
 | 
			
		||||
		#~ proxy = 'proxy.jabber.org'
 | 
			
		||||
		
 | 
			
		||||
		if receiver is None:
 | 
			
		||||
			receiver = file_props['receiver']
 | 
			
		||||
		if sender is None:
 | 
			
		||||
			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, 
 | 
			
		||||
			receiver)
 | 
			
		||||
		file_props['sha_str'] = sha_str
 | 
			
		||||
		listener = gajim.socks5queue.start_listener(self.peerhost[0], port, 
 | 
			
		||||
			sha_str, self.result_socks5_sid, file_props['sid'])
 | 
			
		||||
		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
 | 
			
		||||
			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), 
 | 
			
		||||
			typ = 'set')
 | 
			
		||||
		file_props['request-id'] = 'id_' + file_props['sid']
 | 
			
		||||
| 
						 | 
				
			
			@ -686,11 +690,21 @@ class Connection:
 | 
			
		|||
		streamhost.setAttr('port', str(port))
 | 
			
		||||
		streamhost.setAttr('host', self.peerhost[0])
 | 
			
		||||
		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:
 | 
			
		||||
			fast_tag = query.setTag('fast')
 | 
			
		||||
			fast_tag.setNamespace(common.xmpp.NS_STREAM)
 | 
			
		||||
			
 | 
			
		||||
		self.to_be_sent.append(iq)
 | 
			
		||||
			
 | 
			
		||||
	def _siSetCB(self, con, iq_obj):
 | 
			
		||||
| 
						 | 
				
			
			@ -703,7 +717,7 @@ class Connection:
 | 
			
		|||
			return
 | 
			
		||||
		feature = si.getTag('feature')
 | 
			
		||||
		file_tag = si.getTag('file')
 | 
			
		||||
		file_props = {'type' : 'r'}
 | 
			
		||||
		file_props = {'type': 'r'}
 | 
			
		||||
		for attribute in file_tag.getAttrs():
 | 
			
		||||
			attribute = attribute.encode('utf-8')
 | 
			
		||||
			if attribute in ['name', 'size', 'hash', 'date']:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,10 +22,6 @@
 | 
			
		|||
import socket
 | 
			
		||||
import select
 | 
			
		||||
import os
 | 
			
		||||
try:
 | 
			
		||||
	import fcntl
 | 
			
		||||
except:
 | 
			
		||||
	pass
 | 
			
		||||
import struct
 | 
			
		||||
import sha
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -33,7 +29,7 @@ MAX_BUFF_LEN = 65536
 | 
			
		|||
 | 
			
		||||
class SocksQueue:
 | 
			
		||||
	''' queue for all file requests objects '''
 | 
			
		||||
	def __init__(self, complete_transfer_cb = None, \
 | 
			
		||||
	def __init__(self, complete_transfer_cb = None, 
 | 
			
		||||
		progress_transfer_cb = None):
 | 
			
		||||
		self.connected = 0
 | 
			
		||||
		self.readers = {}
 | 
			
		||||
| 
						 | 
				
			
			@ -62,6 +58,7 @@ class SocksQueue:
 | 
			
		|||
		self.on_success = on_success
 | 
			
		||||
		self.on_failure = on_failure
 | 
			
		||||
		if not self.files_props.has_key(account):
 | 
			
		||||
			print '\n\nFIXME '
 | 
			
		||||
			pass
 | 
			
		||||
			# FIXME ---- show error dialog
 | 
			
		||||
		else:
 | 
			
		||||
| 
						 | 
				
			
			@ -109,6 +106,9 @@ class SocksQueue:
 | 
			
		|||
		return None
 | 
			
		||||
		
 | 
			
		||||
	def get_file_from_sender(self, file_props, account):
 | 
			
		||||
		if file_props is None:
 | 
			
		||||
			return
 | 
			
		||||
		
 | 
			
		||||
		if file_props.has_key('hash') and \
 | 
			
		||||
			self.senders.has_key(file_props['hash']):
 | 
			
		||||
			sender = self.senders[file_props['hash']]
 | 
			
		||||
| 
						 | 
				
			
			@ -344,7 +344,7 @@ class Socks5:
 | 
			
		|||
			except Exception, e:
 | 
			
		||||
				if e.args[0] != 11:
 | 
			
		||||
					# peer stopped reading
 | 
			
		||||
					self.state = 8
 | 
			
		||||
					self.state = 8 # end connection
 | 
			
		||||
					self.fd.close()
 | 
			
		||||
					self.disconnect()
 | 
			
		||||
					self.file_props['error'] = -1
 | 
			
		||||
| 
						 | 
				
			
			@ -352,7 +352,7 @@ class Socks5:
 | 
			
		|||
			self.size += lenn
 | 
			
		||||
			self.file_props['received-len'] = self.size
 | 
			
		||||
			if self.size == int(self.file_props['size']):
 | 
			
		||||
				self.state = 8
 | 
			
		||||
				self.state = 8 # end connection
 | 
			
		||||
				self.file_props['error'] = 0
 | 
			
		||||
				self.fd.close()
 | 
			
		||||
				self.disconnect()
 | 
			
		||||
| 
						 | 
				
			
			@ -369,12 +369,12 @@ class Socks5:
 | 
			
		|||
				self.file_props['stalled'] = True
 | 
			
		||||
			else:
 | 
			
		||||
				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:
 | 
			
		||||
				return None
 | 
			
		||||
			return lenn
 | 
			
		||||
		else:
 | 
			
		||||
			self.state = 8
 | 
			
		||||
			self.state = 8 # end connection
 | 
			
		||||
			self.disconnect()
 | 
			
		||||
			return -1
 | 
			
		||||
	
 | 
			
		||||
| 
						 | 
				
			
			@ -497,15 +497,15 @@ class Socks5:
 | 
			
		|||
		
 | 
			
		||||
	def _get_connect_buff(self):
 | 
			
		||||
		''' Connect request by domain name '''
 | 
			
		||||
		buff = struct.pack('!BBBBB%dsBB' % len(self.host), \
 | 
			
		||||
			0x05, 0x01, 0x00, 0x03, len(self.host), self.host, \
 | 
			
		||||
		buff = struct.pack('!BBBBB%dsBB' % len(self.host), 
 | 
			
		||||
			0x05, 0x01, 0x00, 0x03, len(self.host), self.host, 
 | 
			
		||||
			self.port >> 8, self.port & 0xff)
 | 
			
		||||
		return buff
 | 
			
		||||
	
 | 
			
		||||
	def _get_request_buff(self, msg, command = 0x01):
 | 
			
		||||
		''' Connect request by domain name, 
 | 
			
		||||
		sid sha, instead of domain name (jep 0096) '''
 | 
			
		||||
		buff = struct.pack('!BBBBB%dsBB' % len(msg), \
 | 
			
		||||
		buff = struct.pack('!BBBBB%dsBB' % len(msg), 
 | 
			
		||||
			0x05, command, 0x00, 0x03, len(msg), msg, 0, 0)
 | 
			
		||||
		return buff
 | 
			
		||||
	
 | 
			
		||||
| 
						 | 
				
			
			@ -531,7 +531,7 @@ class Socks5:
 | 
			
		|||
				port, = struct.unpack('!H', buff[host_len + 5:])
 | 
			
		||||
			# file data, comes with auth message (Gaim bug)
 | 
			
		||||
			else: 
 | 
			
		||||
				port, = struct.unpack('!H', buff[host_len + 5 : host_len + 7])
 | 
			
		||||
				port, = struct.unpack('!H', buff[host_len + 5: host_len + 7])
 | 
			
		||||
				self.remaining_buff = buff[host_len + 7:]
 | 
			
		||||
		except:
 | 
			
		||||
			return (None, None, None)
 | 
			
		||||
| 
						 | 
				
			
			@ -550,8 +550,7 @@ class Socks5:
 | 
			
		|||
	def _get_sha1_auth(self):
 | 
			
		||||
		''' get sha of sid + Initiator jid + Target jid '''
 | 
			
		||||
		if self.file_props.has_key('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()
 | 
			
		||||
		return sha.new('%s%s%s' % (self.sid, self.initiator, self.target)).hexdigest()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -585,21 +584,21 @@ class Socks5Sender(Socks5):
 | 
			
		|||
		
 | 
			
		||||
	def main(self):
 | 
			
		||||
		''' initial requests for verifying the connection '''
 | 
			
		||||
		if self.state == 1:
 | 
			
		||||
		if self.state == 1: # initial read
 | 
			
		||||
			buff = self.receive()
 | 
			
		||||
			if not self.connected:
 | 
			
		||||
				return -1
 | 
			
		||||
			mechs = self._parse_auth_buff(buff)
 | 
			
		||||
			if mechs is None:
 | 
			
		||||
				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())
 | 
			
		||||
		elif self.state == 3:
 | 
			
		||||
		elif self.state == 3: # get next request
 | 
			
		||||
			buff = self.receive()
 | 
			
		||||
			(req_type, self.sha_msg, port) = self._parse_request_buff(buff)
 | 
			
		||||
			if req_type != 0x01:
 | 
			
		||||
				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.state += 1 # go to the next step
 | 
			
		||||
		return None
 | 
			
		||||
| 
						 | 
				
			
			@ -609,9 +608,9 @@ class Socks5Sender(Socks5):
 | 
			
		|||
		if self._sock is None:
 | 
			
		||||
			return False
 | 
			
		||||
		try:
 | 
			
		||||
			if self.state in [1, 3, 5]:
 | 
			
		||||
			if self.state in [1, 3, 5]:  # (initial, request, send file)
 | 
			
		||||
				return self.pending_read(timeout)
 | 
			
		||||
			elif self.state in [2, 4]:
 | 
			
		||||
			elif self.state in [2, 4]: # send auth and positive response
 | 
			
		||||
				return True
 | 
			
		||||
		except Exception, e:
 | 
			
		||||
			return False
 | 
			
		||||
| 
						 | 
				
			
			@ -628,7 +627,6 @@ class Socks5Sender(Socks5):
 | 
			
		|||
		if self.queue is not None:
 | 
			
		||||
			self.queue.remove_sender(self.queue_idx)
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
class Socks5Listener:
 | 
			
		||||
	def __init__(self, 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.listen(socket.SOMAXCONN)
 | 
			
		||||
			self._serv.setblocking(False)
 | 
			
		||||
		except Exception, (errno, errstr):
 | 
			
		||||
		except Exception, e:
 | 
			
		||||
			# unable to bind, show error dialog
 | 
			
		||||
			return None
 | 
			
		||||
		self.started = True
 | 
			
		||||
	
 | 
			
		||||
| 
						 | 
				
			
			@ -713,22 +712,22 @@ class Socks5Receiver(Socks5):
 | 
			
		|||
		self.file_props['connected'] = True
 | 
			
		||||
		self.state = 1 # connected
 | 
			
		||||
		self.queue._socket_connected(self.streamhost, self.file_props)
 | 
			
		||||
		return 1
 | 
			
		||||
		return 1 # we are connected
 | 
			
		||||
		
 | 
			
		||||
	def main(self, timeout = 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())
 | 
			
		||||
		elif self.state == 2:
 | 
			
		||||
		elif self.state == 2: # read auth response
 | 
			
		||||
			buff = self.receive()
 | 
			
		||||
			if buff is None or len(buff) != 2:
 | 
			
		||||
				return None
 | 
			
		||||
			version, method = struct.unpack('!BB', buff[:2])
 | 
			
		||||
			if version != 0x05 or method == 0xff:
 | 
			
		||||
				self.disconnect()
 | 
			
		||||
		elif self.state == 3:
 | 
			
		||||
		elif self.state == 3: # send 'connect' request
 | 
			
		||||
			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()
 | 
			
		||||
			if buff == None:
 | 
			
		||||
				return None
 | 
			
		||||
| 
						 | 
				
			
			@ -741,17 +740,17 @@ class Socks5Receiver(Socks5):
 | 
			
		|||
				addrlen = ord(buff[4])
 | 
			
		||||
				address = struct.unpack('!%ds' % addrlen, buff[5:addrlen + 5])
 | 
			
		||||
				portlen = len(buff[addrlen + 5:])
 | 
			
		||||
				if portlen == 1: # Gaim bug :)
 | 
			
		||||
				if portlen == 1: 
 | 
			
		||||
					port, = struct.unpack('!B', buff[addrlen + 5])
 | 
			
		||||
				elif portlen == 2:
 | 
			
		||||
					port, = struct.unpack('!H', buff[addrlen + 5:])
 | 
			
		||||
				else:
 | 
			
		||||
				else: # Gaim bug :)
 | 
			
		||||
					port, = struct.unpack('!H', buff[addrlen + 5: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:
 | 
			
		||||
				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':
 | 
			
		||||
				self.fd = open(self.file_props['file-name'])
 | 
			
		||||
				self.file_props['error'] = 0
 | 
			
		||||
| 
						 | 
				
			
			@ -763,20 +762,20 @@ class Socks5Receiver(Socks5):
 | 
			
		|||
				self.file_props['received-len'] = 0
 | 
			
		||||
				self.pauses = 0
 | 
			
		||||
				self.send_raw(self._get_nl_byte())
 | 
			
		||||
			self.state = 6
 | 
			
		||||
			self.state = 6 # send/get file contents
 | 
			
		||||
		if self.state < 6:
 | 
			
		||||
			self.state += 1
 | 
			
		||||
			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):
 | 
			
		||||
		''' 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:
 | 
			
		||||
			return False
 | 
			
		||||
		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)
 | 
			
		||||
			elif self.state in [1, 3, 5]:
 | 
			
		||||
			elif self.state in [1, 3, 5]: # auth types, connect request
 | 
			
		||||
				return True
 | 
			
		||||
		except Exception, e:
 | 
			
		||||
			return False
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue