Subversion Repositories HomeAutomation

Rev

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