Changes in / [988d75c:ae8cc50]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
skype/skyped.py
r988d75c rae8cc50 26 26 import locale 27 27 import time 28 import gobject29 28 import socket 30 29 import getopt … … 34 33 from traceback import print_exception 35 34 import ssl 35 import select 36 import threading 36 37 37 38 __version__ = "0.1.1" … … 42 43 if type != KeyboardInterrupt: 43 44 print_exception(type, value, tb) 44 gobject.MainLoop().quit() 45 options.conn.close() 45 if options.conn: options.conn.close() 46 46 # shut down client if it's running 47 47 try: … … 53 53 sys.excepthook = eh 54 54 55 def input_handler(fd, io_condition): 56 global options 55 def wait_for_lock(lock, timeout_to_print, timeout, msg): 56 start = time.time() 57 locked = lock.acquire(0) 58 while not(locked): 59 time.sleep(0.5) 60 if timeout_to_print and (time.time() - timeout_to_print > start): 61 dprint("%s: Waited %f seconds" % \ 62 (msg, time.time() - start)) 63 timeout_to_print = False 64 if timeout and (time.time() - timeout > start): 65 dprint("%s: Waited %f seconds, giving up" % \ 66 (msg, time.time() - start)) 67 return False 68 locked = lock.acquire(0) 69 return True 70 71 def input_handler(fd): 72 global options 73 global skype 57 74 if options.buf: 58 75 for i in options.buf: 59 76 skype.send(i.strip()) 60 77 options.buf = None 78 return True 61 79 else: 62 try: 63 input = fd.recv(1024) 64 except Exception, s: 65 dprint("Warning, receiving 1024 bytes failed (%s)." % s) 66 fd.close() 67 return False 68 for i in input.split("\n"): 69 skype.send(i.strip()) 70 return True 80 close_socket = False 81 if wait_for_lock(options.lock, 3, 10, "input_handler"): 82 try: 83 input = fd.recv(1024) 84 options.lock.release() 85 except Exception, s: 86 dprint("Warning, receiving 1024 bytes failed (%s)." % s) 87 fd.close() 88 options.conn = False 89 options.lock.release() 90 return False 91 for i in input.split("\n"): 92 if i.strip() == "SET USERSTATUS OFFLINE": 93 close_socket = True 94 skype.send(i.strip()) 95 return not(close_socket) 71 96 72 97 def skype_idle_handler(skype): … … 74 99 c = skype.skype.Command("PING", Block=True) 75 100 skype.skype.SendCommand(c) 101 dprint("... skype pinged") 76 102 except Skype4Py.SkypeAPIError, s: 77 103 dprint("Warning, pinging Skype failed (%s)." % (s)) … … 79 105 80 106 def send(sock, txt): 81 from time import sleep107 global options 82 108 count = 1 83 109 done = False 84 while (not done) and (count < 10): 85 try: 86 sock.send(txt) 87 done = True 88 except Exception, s: 89 count += 1 90 dprint("Warning, sending '%s' failed (%s). count=%d" % (txt, s, count)) 91 sleep(1) 110 while (not done) and (count < 10) and options.conn: 111 if wait_for_lock(options.lock, 3, 10, "socket send"): 112 try: 113 if options.conn: sock.send(txt) 114 options.lock.release() 115 done = True 116 except Exception, s: 117 options.lock.release() 118 count += 1 119 dprint("Warning, sending '%s' failed (%s). count=%d" % (txt, s, count)) 120 time.sleep(1) 92 121 if not done: 93 options.conn.close() 122 if options.conn: options.conn.close() 123 options.conn = False 124 return done 94 125 95 126 def bitlbee_idle_handler(skype): 127 global options 128 done = False 96 129 if options.conn: 97 130 try: 98 131 e = "PING" 99 send(options.conn, "%s\n" % e) 132 done = send(options.conn, "%s\n" % e) 133 dprint("... pinged Bitlbee") 100 134 except Exception, s: 101 135 dprint("Warning, sending '%s' failed (%s)." % (e, s)) 102 options.conn.close() 103 return True 104 105 def server(host, port): 136 if options.conn: options.conn.close() 137 options.conn = False 138 done = False 139 return done 140 141 def server(host, port, skype): 106 142 global options 107 143 sock = socket.socket() … … 109 145 sock.bind((host, port)) 110 146 sock.listen(1) 111 gobject.io_add_watch(sock, gobject.IO_IN, listener) 112 113 def listener(sock, *args): 114 global options 147 dprint("Waiting for connection...") 148 listener(sock, skype) 149 150 def listener(sock, skype): 151 global options 152 if not(wait_for_lock(options.lock, 3, 10, "listener")): return False 115 153 rawsock, addr = sock.accept() 116 154 options.conn = ssl.wrap_socket(rawsock, … … 123 161 options.conn.handshake() 124 162 except Exception: 163 options.lock.release() 125 164 dprint("Warning, handshake failed, closing connection.") 126 165 return False … … 136 175 dprint("Warning, receiving 1024 bytes failed (%s)." % s) 137 176 options.conn.close() 177 options.conn = False 178 options.lock.release() 138 179 return False 139 180 if ret == 2: 140 181 dprint("Username and password OK.") 141 182 options.conn.send("PASSWORD OK\n") 142 gobject.io_add_watch(options.conn, gobject.IO_IN, input_handler) 183 options.lock.release() 184 serverloop(options, skype) 143 185 return True 144 186 else: 145 187 dprint("Username and/or password WRONG.") 146 188 options.conn.send("PASSWORD KO\n") 189 options.conn.close() 190 options.conn = False 191 options.lock.release() 147 192 return False 148 193 … … 188 233 # everybody will be happy 189 234 e = i.encode('UTF-8') 190 dprint('<< ' + e)191 235 if options.conn: 236 dprint('<< ' + e) 192 237 try: 238 # I called the send function really_send 193 239 send(options.conn, e + "\n") 194 240 except Exception, s: 195 241 dprint("Warning, sending '%s' failed (%s)." % (e, s)) 196 options.conn.close() 242 if options.conn: options.conn.close() 243 options.conn = False 244 else: 245 dprint('---' + e) 197 246 198 247 def send(self, msg_text): 199 248 if not len(msg_text) or msg_text == "PONG": 249 if msg_text == "PONG": options.last_bitlbee_pong = time.time() 200 250 return 201 251 try: … … 252 302 -v --version display version information""" % (self.cfgpath, self.host, self.port) 253 303 sys.exit(ret) 304 305 def serverloop(options, skype): 306 timeout = 1; # in seconds 307 skype_ping_period = 5 308 bitlbee_ping_period = 10 309 bitlbee_pong_timeout = 30 310 now = time.time() 311 skype_ping_start_time = now 312 bitlbee_ping_start_time = now 313 options.last_bitlbee_pong = now 314 in_error = [] 315 handler_ok = True 316 while (len(in_error) == 0) and handler_ok and options.conn: 317 ready_to_read, ready_to_write, in_error = \ 318 select.select([options.conn], [], [options.conn], \ 319 timeout) 320 now = time.time() 321 handler_ok = len(in_error) == 0 322 if (len(ready_to_read) == 1) and handler_ok: 323 handler_ok = input_handler(ready_to_read.pop()) 324 # don't ping bitlbee/skype if they already received data 325 now = time.time() # allow for the input_handler to take some time 326 bitlbee_ping_start_time = now 327 skype_ping_start_time = now 328 options.last_bitlbee_pong = now 329 if (now - skype_ping_period > skype_ping_start_time) and handler_ok: 330 handler_ok = skype_idle_handler(skype) 331 skype_ping_start_time = now 332 if now - bitlbee_ping_period > bitlbee_ping_start_time: 333 handler_ok = bitlbee_idle_handler(skype) 334 bitlbee_ping_start_time = now 335 if options.last_bitlbee_pong: 336 if (now - options.last_bitlbee_pong) > bitlbee_pong_timeout: 337 dprint("Bitlbee pong timeout") 338 # TODO is following line necessary? Should there be a options.conn.unwrap() somewhere? 339 # options.conn.shutdown() 340 if options.conn: options.conn.close() 341 options.conn = False 342 else: 343 dprint("%f seconds since last PONG" % (now - options.last_bitlbee_pong)) 344 else: 345 options.last_bitlbee_pong = now 346 dprint("Serverloop done") 254 347 255 348 if __name__=='__main__': … … 317 410 else: 318 411 dprint('skyped is started on port %s' % options.port) 319 server(options.host, options.port)320 412 try: 321 413 skype = SkypeApi() 322 414 except Skype4Py.SkypeAPIError, s: 323 415 sys.exit("%s. Are you sure you have started Skype?" % s) 324 gobject.timeout_add(2000, skype_idle_handler, skype) 325 gobject.timeout_add(60000, bitlbee_idle_handler, skype) 326 gobject.MainLoop().run() 416 while 1: 417 options.conn = False 418 options.lock = threading.Lock() 419 server(options.host, options.port, skype)
Note: See TracChangeset
for help on using the changeset viewer.