Subversion Repositories HomeAutomation

Rev

Details | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
742 olof 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
743 olof 20
        self.clientSocks = [] # may not be gc'd between instances of object
742 olof 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
743 olof 107
 
108
    def getClients(self):
109
        return self.serverThread.clientSocks
742 olof 110
 
111
    def readAll(self):
112
        cldata = []
113
        self.serverThread.clientSocksLock.acquire()
114
        for clsock,addr in self.serverThread.clientSocks:
115
            try:
743 olof 116
                data = clsock.recv(1024)
742 olof 117
            except Exception, e:
743 olof 118
                log.debug('TCPServer client ' + str(addr) + ' socket error: ' + str(e))
742 olof 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:
743 olof 131
                log.debug('TCPServer client ' + str(addr) + ' socket error: ' + str(e))
132
                self.serverThread.clientSocks.remove((clsock,addr))
742 olof 133
                self.serverThread.clientSocksLock.release()
743 olof 134
                return False
742 olof 135
        self.serverThread.clientSocksLock.release()
743 olof 136
        return True