Subversion Repositories HomeAutomation

Rev

Rev 743 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. import socket
  2. from threading import Thread
  3. from threading import Lock
  4. import logging as log
  5. import time
  6.  
  7. class TCPServerThread(Thread):
  8.    
  9.     ownerNotifier = None
  10.     sock = None
  11.     terminated = False
  12.    
  13.     clientSocks = []
  14.     clientSocksLock = None
  15.    
  16.     def __init__ (self, sock, ownerNotifier):
  17.         Thread.__init__(self)
  18.         self.sock = sock
  19.         self.ownerNotifier = ownerNotifier
  20.         self.clientSocks = [] # may not be gc'd between instances of object
  21.         self.clientSocksLock = Lock()
  22.        
  23.     def cleanup(self):
  24.         self.sock.close()
  25.         self.clientSocksLock.acquire()
  26.         for clsock, addr in self.clientSocks:
  27.             clsock.close()
  28.         self.clientSocksLock.release()
  29.  
  30.         if self.ownerNotifier is not None:
  31.             self.ownerNotifier.notify(self.ownerNotifier.TERMINATE)
  32.  
  33.     def run(self):
  34.         try:
  35.             log.debug('TCPServerThread.run')
  36.             while not self.terminated:
  37.                 try:
  38.                     conn, addr = self.sock.accept()
  39.                     print 'Client connected from ' + str(addr)
  40.                     conn.setblocking(0)
  41.                     self.clientSocksLock.acquire()
  42.                     self.clientSocks.append((conn, addr))
  43.                     self.clientSocksLock.release()
  44.                 except socket.timeout:
  45.                     pass
  46.             self.cleanup()
  47.         except: # sys.excepthook does not work in threads
  48.             import traceback
  49.             traceback.print_exc()
  50.             self.terminated = True
  51.             self.cleanup()
  52.    
  53.     def terminate(self):
  54.         log.debug('TCPServerThread.terminate')
  55.         self.terminated = True
  56.  
  57. class TCPServer():
  58.    
  59.     serverThread = None
  60.     ownerNotifier = None
  61.     port = 50007
  62.     host = ''
  63.    
  64.     def __init__(self, port, ownerNotifier = None):
  65.         self.port = port
  66.         self.ownerNotifier = ownerNotifier
  67.        
  68.     def start(self):
  69.         if self.serverThread is not None:
  70.             log.debug('TCPServer is already running')
  71.             return
  72.         try:
  73.             s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  74.         except Exception, e:
  75.             print 'TCP Server start failed:', e
  76.             return False
  77.         try:
  78.             s.bind((self.host, self.port))
  79.             s.listen(1)
  80.             s.settimeout(0.5)
  81.         except Exception, e:
  82.             print 'TCP Server start failed:', e
  83.             s.close()
  84.             return False
  85.         try:
  86.             self.serverThread = TCPServerThread(s, self.ownerNotifier)
  87.             self.serverThread.start()
  88.         except Exception, e:
  89.             print 'TCP Server start failed:', e
  90.             if self.serverThread is not None and self.serverThread.running():
  91.                 self.serverThread.terminate()
  92.             s.close()
  93.             return False
  94.         return True
  95.  
  96.     def stop(self):
  97.         if self.running():
  98.             self.serverThread.terminate()
  99.         else:
  100.             log.debug('TCPServer not started, or already stopped')
  101.  
  102.     def running(self):
  103.         if self.serverThread is not None:
  104.             return not self.serverThread.terminated
  105.         else:
  106.             return False
  107.        
  108.     def getClients(self):
  109.         return self.serverThread.clientSocks
  110.  
  111.     def readAll(self):
  112.         cldata = []
  113.         self.serverThread.clientSocksLock.acquire()
  114.         for clsock,addr in self.serverThread.clientSocks:
  115.             try:
  116.                 data = clsock.recv(1024)
  117.             except Exception, e:
  118.                 log.debug('TCPServer client ' + str(addr) + ' socket error: ' + str(e))
  119.                 self.serverThread.clientSocksLock.release()
  120.                 return None
  121.             cldata.append((addr, data))
  122.         self.serverThread.clientSocksLock.release()
  123.         return cldata
  124.  
  125.     def writeAll(self, data):
  126.         self.serverThread.clientSocksLock.acquire()
  127.         for clsock,addr in self.serverThread.clientSocks:
  128.             try:
  129.                 clsock.send(data)
  130.             except Exception, e:
  131.                 log.debug('TCPServer client ' + str(addr) + ' socket error: ' + str(e))
  132.                 self.serverThread.clientSocks.remove((clsock,addr))
  133.                 self.serverThread.clientSocksLock.release()
  134.                 return False
  135.         self.serverThread.clientSocksLock.release()
  136.         return True
  137.