diff options
| author | Wilmer van der Gaast <wilmer@gaast.net> | 2013-02-21 13:16:26 +0000 | 
|---|---|---|
| committer | Wilmer van der Gaast <wilmer@gaast.net> | 2013-02-21 13:16:26 +0000 | 
| commit | 12f500f085fe715b62e13c9b67b23f952c100a21 (patch) | |
| tree | ce11dc48779b7ca5f70c48de39b720a1c320ae31 /protocols/skype/skyped.py | |
| parent | e4f5ca868fc4313a6a9a00c5eda0a03767abc703 (diff) | |
| parent | 9754c2fd0e4dbe65e13878b947091483bfff102a (diff) | |
Merge from vmiklos. Mostly Skype stuff and further deprecating a nogaim
function.
Diffstat (limited to 'protocols/skype/skyped.py')
| -rw-r--r-- | protocols/skype/skyped.py | 210 | 
1 files changed, 94 insertions, 116 deletions
| diff --git a/protocols/skype/skyped.py b/protocols/skype/skyped.py index f1777d0b..cb57b7ec 100644 --- a/protocols/skype/skyped.py +++ b/protocols/skype/skyped.py @@ -1,32 +1,30 @@  #!/usr/bin/env python2.7 -#  +#  #   skyped.py -#   +#  #   Copyright (c) 2007-2013 by Miklos Vajna <vmiklos@vmiklos.hu>  #  #   This program is free software; you can redistribute it and/or modify  #   it under the terms of the GNU General Public License as published by  #   the Free Software Foundation; either version 2 of the License, or  #   (at your option) any later version. -#  +#  #   This program is distributed in the hope that it will be useful,  #   but WITHOUT ANY WARRANTY; without even the implied warranty of  #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  #   GNU General Public License for more details. -#   +#  #   You should have received a copy of the GNU General Public License  #   along with this program; if not, write to the Free Software -#   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,  +#   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,  #   USA.  #  import sys  import os  import signal -import locale  import time  import socket -import getopt  import Skype4Py  import hashlib  from ConfigParser import ConfigParser, NoOptionError @@ -53,11 +51,12 @@ def eh(type, value, tb):  		gobject.MainLoop().quit()  	if options.conn:  		options.conn.close() -	# shut down client if it's running -	try: -		skype.skype.Client.Shutdown() -	except NameError: -		pass +	if not options.dont_start_skype: +		# shut down client if it's running +		try: +			skype.skype.Client.Shutdown() +		except NameError: +			pass  	sys.exit("Exiting.")  sys.excepthook = eh @@ -124,35 +123,30 @@ def skype_idle_handler(skype):  		time.sleep(1)  	return True -def send(sock, txt): +def send(sock, txt, tries=10):  	global options -	from time import sleep -	count = 1 -	done = False  	if hasgobject: -		while (not done) and (count < 10): -			try: -				sock.send(txt) -				done = True -			except Exception, s: -				count += 1 -				dprint("Warning, sending '%s' failed (%s). count=%d" % (txt, s, count)) -				sleep(1) -		if not done: +		if not options.conn: return +		try: +			sock.sendall(txt) +		except socket.error as s: +			dprint("Warning, sending '%s' failed (%s)." % (txt, s))  			options.conn.close() +			options.conn = False  	else: -		while (not done) and (count < 10) and options.conn: +		for attempt in xrange(1, tries+1): +			if not options.conn: break  			if wait_for_lock(options.lock, 3, 10, "socket send"):  				try: -					 if options.conn: sock.send(txt) +					 if options.conn: sock.sendall(txt)  					 options.lock.release() -					 done = True -				except Exception, s: +				except socket.error as s:  					options.lock.release() -					count += 1  					dprint("Warning, sending '%s' failed (%s). count=%d" % (txt, s, count)) -					sleep(1) -		if not done: +					time.sleep(1) +				else: +					break +		else:  			if options.conn:  				options.conn.close()  			options.conn = False @@ -207,9 +201,13 @@ def listener(sock, skype):  			certfile=options.config.sslcert,  			keyfile=options.config.sslkey,  			ssl_version=ssl.PROTOCOL_TLSv1) -	except ssl.SSLError: -		dprint("Warning, SSL init failed, did you create your certificate?") -		return False +	except (ssl.SSLError, socket.error) as err: +		if isinstance(err, ssl.SSLError): +			dprint("Warning, SSL init failed, did you create your certificate?") +			return False +		else: +			dprint('Warning, SSL init failed') +			return True  	if hasattr(options.conn, 'handshake'):  		try:  			options.conn.handshake() @@ -280,7 +278,7 @@ class MockedSkype:  	def __init__(self, mock):  		sock = open(mock)  		self.lines = sock.readlines() -	 +  	def SendCommand(self, c):  		pass @@ -309,10 +307,12 @@ class MockedSkype:  class SkypeApi:  	def __init__(self, mock): +		global options  		if not mock:  			self.skype = Skype4Py.Skype()  			self.skype.OnNotify = self.recv -			self.skype.Client.Start() +			if not options.dont_start_skype: +				self.skype.Client.Start()  		else:  			self.skype = MockedSkype(mock) @@ -379,43 +379,6 @@ class SkypeApi:  		except Skype4Py.SkypeAPIError, s:  			dprint("Warning, sending '%s' failed (%s)." % (e, s)) -class Options: -	def __init__(self): -		self.cfgpath = os.path.join(os.environ['HOME'], ".skyped", "skyped.conf") -		# fall back to system-wide settings -		self.syscfgpath = "/usr/local/etc/skyped/skyped.conf" -		if os.path.exists(self.syscfgpath) and not os.path.exists(self.cfgpath): -			self.cfgpath = self.syscfgpath -		self.daemon = True -		self.debug = False -		self.help = False -		self.host = "0.0.0.0" -		self.log = None -		self.port = None -		self.version = False -		# well, this is a bit hackish. we store the socket of the last connected client -		# here and notify it. maybe later notify all connected clients? -		self.conn = None -		# this will be read first by the input handler -		self.buf = None -		self.mock = None - - -	def usage(self, ret): -		print """Usage: skyped [OPTION]... - -skyped is a daemon that acts as a tcp server on top of a Skype instance. - -Options: -	-c      --config        path to configuration file (default: %s) -	-d	--debug		enable debug messages -	-h	--help		this help -	-H	--host		set the tcp host, supports IPv4 and IPv6 (default: %s) -	-l      --log           set the log file in background mode (default: none) -	-n	--nofork	don't run as daemon in the background -	-p	--port		set the tcp port (default: %s) -	-v	--version	display version information""" % (self.cfgpath, self.host, self.port) -		sys.exit(ret)  def serverloop(options, skype):  	timeout = 1; # in seconds @@ -458,60 +421,72 @@ def serverloop(options, skype):  			else:  				options.last_bitlbee_pong = now -if __name__=='__main__': -	options = Options() -	try: -		opts, args = getopt.getopt(sys.argv[1:], "c:dhH:l:m:np:v", ["config=", "debug", "help", "host=", "log=", "mock=", "nofork", "port=", "version"]) -	except getopt.GetoptError: -		options.usage(1) -	for opt, arg in opts: -		if opt in ("-c", "--config"): -			options.cfgpath = arg -		elif opt in ("-d", "--debug"): -			options.debug = True -		elif opt in ("-h", "--help"): -			options.help = True -		elif opt in ("-H", "--host"): -			options.host = arg -		elif opt in ("-l", "--log"): -			options.log = arg -		elif opt in ("-m", "--mock"): -			options.mock = arg -		elif opt in ("-n", "--nofork"): -			options.daemon = False -		elif opt in ("-p", "--port"): -			options.port = int(arg) -		elif opt in ("-v", "--version"): -			options.version = True -	if options.help: -		options.usage(0) -	elif options.version: + +def main(args=None): +	global options +	global skype + +	cfgpath = os.path.join(os.environ['HOME'], ".skyped", "skyped.conf") +	syscfgpath = "/usr/local/etc/skyped/skyped.conf" +	if not os.path.exists(cfgpath) and os.path.exists(syscfgpath): +		cfgpath = syscfgpath # fall back to system-wide settings +	port = 2727 + +	import argparse +	parser = argparse.ArgumentParser() +	parser.add_argument('-c', '--config', +		metavar='path', default=cfgpath, +		help='path to configuration file (default: %(default)s)') +	parser.add_argument('-H', '--host', default='0.0.0.0', +		help='set the tcp host, supports IPv4 and IPv6 (default: %(default)s)') +	parser.add_argument('-p', '--port', type=int, +		help='set the tcp port (default: %(default)s)') +	parser.add_argument('-l', '--log', metavar='path', +		help='set the log file in background mode (default: none)') +	parser.add_argument('-v', '--version', action='store_true', help='display version information') +	parser.add_argument('-n', '--nofork', +		action='store_true', help="don't run as daemon in the background") +	parser.add_argument('-s', '--dont-start-skype', action='store_true', +		help="assume that skype is running independently, don't try to start/stop it") +	parser.add_argument('-m', '--mock', help='fake interactions with skype (only useful for tests)') +	parser.add_argument('-d', '--debug', action='store_true', help='enable debug messages') +	options = parser.parse_args(sys.argv[1:] if args is None else args) + +	if options.version:  		print "skyped %s" % __version__  		sys.exit(0) -	# parse our config -	if not os.path.exists(options.cfgpath): -		print "Can't find configuration file at '%s'." % options.cfgpath -		print "Use the -c option to specify an alternate one." -		sys.exit(1) + +	# well, this is a bit hackish. we store the socket of the last connected client +	# here and notify it. maybe later notify all connected clients? +	options.conn = None +	# this will be read first by the input handler +	options.buf = None + +	if not os.path.exists(options.config): +		parser.error(( "Can't find configuration file at '%s'." +			"Use the -c option to specify an alternate one." )% options.config) + +	cfgpath = options.config  	options.config = ConfigParser() -	options.config.read(options.cfgpath) -	options.config.username = options.config.get('skyped', 'username').split('#')[0] -	options.config.password = options.config.get('skyped', 'password').split('#')[0] -	options.config.sslkey = os.path.expanduser(options.config.get('skyped', 'key').split('#')[0]) -	options.config.sslcert = os.path.expanduser(options.config.get('skyped', 'cert').split('#')[0]) +	options.config.read(cfgpath) +	options.config.username = options.config.get('skyped', 'username').split('#', 1)[0] +	options.config.password = options.config.get('skyped', 'password').split('#', 1)[0] +	options.config.sslkey = os.path.expanduser(options.config.get('skyped', 'key').split('#', 1)[0]) +	options.config.sslcert = os.path.expanduser(options.config.get('skyped', 'cert').split('#', 1)[0]) +  	# hack: we have to parse the parameters first to locate the  	# config file but the -p option should overwrite the value from  	# the config file  	try: -		options.config.port = int(options.config.get('skyped', 'port').split('#')[0]) +		options.config.port = int(options.config.get('skyped', 'port').split('#', 1)[0])  		if not options.port:  			options.port = options.config.port  	except NoOptionError:  		pass  	if not options.port: -		options.port = 2727 -	dprint("Parsing config file '%s' done, username is '%s'." % (options.cfgpath, options.config.username)) -	if options.daemon: +		options.port = port +	dprint("Parsing config file '%s' done, username is '%s'." % (cfgpath, options.config.username)) +	if not options.nofork:  		pid = os.fork()  		if pid == 0:  			nullin = file(os.devnull, 'r') @@ -539,3 +514,6 @@ if __name__=='__main__':  			options.conn = False  			options.lock = threading.Lock()  			server(options.host, options.port, skype) + + +if __name__ == '__main__': main() | 
