source: trunk/Puzzlebox/Synapse/Server.py @ 413

Last change on this file since 413 was 376, checked in by sc, 8 years ago
  • Tweaks on Jigsaw side
  • Property svn:executable set to *
File size: 8.5 KB
Line 
1# -*- coding: utf-8 -*-
2
3# Copyright Puzzlebox Productions, LLC (2010-2012)
4#
5# This code is released under the GNU Pulic License (GPL) version 2
6# For more information please refer to http://www.gnu.org/copyleft/gpl.html
7
8__changelog__ = """\
9Last Update: 2012.03.30
10"""
11
12### IMPORTS ###
13
14import os, sys, time
15
16import simplejson as json
17
18import Puzzlebox.Synapse.Configuration as configuration
19
20if configuration.ENABLE_PYSIDE:
21        try:
22                import PySide as PyQt4
23                from PySide import QtCore, QtGui, QtNetwork
24        except Exception, e:
25                print "ERROR: Exception importing PySide:",
26                print e
27                configuration.ENABLE_PYSIDE = False
28        else:
29                print "INFO: [Synapse:Server] Using PySide module"
30
31if not configuration.ENABLE_PYSIDE:
32        print "INFO: [Synapse:Server] Using PyQt4 module"
33        from PyQt4 import QtCore, QtGui, QtNetwork
34
35
36#####################################################################
37# Globals
38#####################################################################
39
40DEBUG = configuration.DEBUG
41
42COMMUNICATION_MODE = 'Emit Signal'
43#COMMUNICATION_MODE = 'Call Parent'
44
45SERVER_INTERFACE = configuration.SYNAPSE_SERVER_INTERFACE
46SERVER_PORT = configuration.SYNAPSE_SERVER_PORT
47DEFAULT_DEVICE_MODEL = 'NeuroSky MindWave'
48THINKGEAR_DEVICE_SERIAL_PORT = configuration.THINKGEAR_DEVICE_SERIAL_PORT
49
50CLIENT_NO_REPLY_WAIT = configuration.CLIENT_NO_REPLY_WAIT * 1000
51
52FLASH_POLICY_FILE_REQUEST = configuration.FLASH_POLICY_FILE_REQUEST
53FLASH_SOCKET_POLICY_FILE = configuration.FLASH_SOCKET_POLICY_FILE
54
55DELIMITER = configuration.SYNAPSE_DELIMITER
56
57MESSAGE_FREQUENCY_TIMER = 1 * 1000 # 1 Hz (1000 ms)
58
59ENABLE_SIMULATE_HEADSET_DATA = configuration.THINKGEAR_ENABLE_SIMULATE_HEADSET_DATA
60
61DEFAULT_PACKET = {}
62DEFAULT_RESPONSE_MESSAGE = DEFAULT_PACKET
63
64#####################################################################
65# Classes
66#####################################################################
67
68class puzzlebox_synapse_server(QtCore.QThread):
69       
70        def __init__(self, log, \
71                          server_interface=SERVER_INTERFACE, \
72                          server_port=SERVER_PORT, \
73                          device_model=DEFAULT_DEVICE_MODEL, \
74                          device_address=THINKGEAR_DEVICE_SERIAL_PORT, \
75                          emulate_headset_data=ENABLE_SIMULATE_HEADSET_DATA, \
76                          DEBUG=DEBUG, \
77                          parent=None):
78               
79                QtCore.QThread.__init__(self,parent)
80               
81                self.log = log
82                self.DEBUG = DEBUG
83                self.parent = parent
84               
85                self.server_interface = server_interface
86                self.server_port = server_port
87                self.device_address = device_address
88                self.device_model = device_model
89                self.emulate_headset_data = emulate_headset_data
90               
91                self.connection_timestamp = time.time()
92                self.session_start_timestamp = time.time()
93               
94                self.connections = []
95                self.packet_queue = []
96               
97                self.connect(self, \
98                             QtCore.SIGNAL("sendPacket()"), \
99                             self.sendPacketQueue)
100               
101               
102                self.configureNetwork()
103       
104       
105        ##################################################################
106       
107        def configureNetwork(self):
108       
109                #self.blockSize = 0
110                self.socket = QtNetwork.QTcpServer()
111                self.socket.name = 'Synapse:Server'
112               
113                if self.DEBUG:
114                        print "<---- [%s] Initializing server on %s:%i" % \
115                           (self.socket.name, self.server_interface, self.server_port)
116               
117               
118                if ((self.server_interface == '') or \
119                         (self.server_interface == '*')):
120                        address=QtNetwork.QHostAddress.Any
121                else:
122                        #address=self.server_interface
123                        address=QtNetwork.QHostAddress(self.server_interface)
124               
125               
126                result = self.socket.listen(address, self.server_port)
127               
128               
129                if not result:
130                        try:
131                                QtGui.QMessageBox.information( \
132                                self.parent, \
133                                self.socket.name, \
134                                "Unable to start the server on %s:%i" % \
135                                (self.server_interface, self.server_port))
136                        except:
137                                pass
138                       
139                        if self.DEBUG:
140                                print "ERROR [%s] Unable to start the server:" % self.socket.name,
141                                print self.socket.errorString()
142                       
143                        self.socket.close()
144                        return
145               
146               
147                self.socket.newConnection.connect(self.processConnection)
148                #self.socket.error.connect(self.displayError)
149       
150       
151        ##################################################################
152       
153        def deleteDisconnected(self):
154               
155                connection_index = 0
156               
157                for connection in self.connections:
158                       
159                        try:
160                       
161                                if ((connection.state() != QtNetwork.QAbstractSocket.ConnectingState) and \
162                                        (connection.state() != QtNetwork.QAbstractSocket.ConnectedState)):
163                                       
164                                        if self.DEBUG:
165                                                print "- - [%s] Deleting disconnected socket" % self.socket.name
166                                       
167                                        connection.deleteLater()
168                                        # Delete references to disconnected sockets
169                                        del (self.connections[connection_index])
170                       
171                        except:
172                                # Delete references to sockets throwing exceptions
173                                del (self.connections[connection_index])
174                       
175                        connection_index += 1
176       
177       
178        ##################################################################
179       
180        def processConnection(self):
181               
182                clientConnection = self.socket.nextPendingConnection()
183                clientConnection.disconnected.connect(self.deleteDisconnected)
184               
185                self.connections.append(clientConnection)
186               
187                self.clientConnection = clientConnection
188               
189                # the next connected client to enter the readyRead state
190                # will be processed first
191                clientConnection.readyRead.connect(self.processClientConnection)
192       
193       
194        ##################################################################
195       
196        def processClientConnection(self):
197               
198                clientConnection = self.clientConnection
199               
200                socket_buffer = clientConnection.readAll()
201               
202                for packet in socket_buffer.split(DELIMITER):
203                       
204                        data_to_process = None
205                       
206                        if packet != '':
207                               
208                                try:
209                                        data_to_process = json.loads(packet.data())
210                               
211                                except Exception, e:
212                                       
213                                        # Special socket handling for Flash applications
214                                        if (packet == FLASH_POLICY_FILE_REQUEST):
215                                               
216                                                if self.DEBUG:
217                                                        print "--> [%s] Flash policy file requested" % self.socket.name
218                                               
219                                                data_to_process = packet.data()
220                                       
221                                       
222                                        else:
223                                               
224                                                if self.DEBUG:
225                                                        print "--> [%s] Partial data received (or error:" % self.socket.name,
226                                                        print e
227                                                        print ")."
228                                                       
229                                                        print "packet data:",
230                                                        print packet.data()
231                               
232                               
233                                else:
234                                       
235                                        if self.DEBUG:
236                                                print "--> [%s] Received:" % self.socket.name,
237                                                print data_to_process
238                               
239                               
240                                if (data_to_process != None):
241                                       
242                                        response = self.processData(data_to_process)
243                                       
244                                        if (response != None):
245                                               
246                                                self.sendResponse(clientConnection, response)
247       
248       
249        ##################################################################
250       
251        def sendResponse(self, connection, response, disconnect_after_sending=False):
252               
253                # Special socket handling for Flash applications
254                if (response == FLASH_SOCKET_POLICY_FILE):
255                        data = response
256                else:
257                        data = json.dumps(response)
258                        data = data + DELIMITER
259               
260                if connection.waitForConnected(CLIENT_NO_REPLY_WAIT):
261                       
262                        if self.DEBUG > 1:
263                                print "<-- [%s] Sending:" % self.socket.name,
264                                print data
265                       
266                        connection.write(data)
267                       
268                        connection.waitForBytesWritten(CLIENT_NO_REPLY_WAIT)
269                       
270                        if disconnect_after_sending:
271                                connection.disconnectFromHost()
272       
273       
274        ##################################################################
275       
276        def emitSendPacketSignal(self):
277               
278                self.emit(QtCore.SIGNAL("sendPacket()"))
279       
280       
281        ##################################################################
282       
283        def sendPacketQueue(self):
284               
285                if self.connections != []:
286                       
287                        while (len(self.packet_queue) > 0):
288                               
289                                packet = self.packet_queue[0]
290                                del self.packet_queue[0]
291                               
292                                for connection in self.connections:
293                                       
294                                        if connection.state() == QtNetwork.QAbstractSocket.ConnectedState:
295                                               
296                                                self.sendResponse(connection, packet)
297       
298       
299        ##################################################################
300       
301        def processData(self, data):
302               
303                response = None
304               
305                # Special socket handling for Flash applications
306                if (data == FLASH_POLICY_FILE_REQUEST):
307                       
308                        response = FLASH_SOCKET_POLICY_FILE
309               
310               
311                return(response)
312       
313       
314        ##################################################################
315       
316        def updateSessionStartTime(self, session_start_timestamp):
317               
318                self.session_start_timestamp = session_start_timestamp
319       
320       
321        ##################################################################
322       
323        def run(self):
324               
325                if self.DEBUG:
326                        print "<---- [%s] Main thread running" % self.socket.name
327               
328               
329                self.exec_()
330       
331       
332        ##################################################################
333       
334        def exitThread(self, callThreadQuit=True):
335               
336               
337                for server in self.protocolServers:
338                        server.exitThread()
339               
340                self.socket.close()
341               
342                if callThreadQuit:
343                        QtCore.QThread.quit(self)
344               
345                if self.parent == None:
346                        sys.exit()
347       
348       
349        ##################################################################
350       
351        def stop(self):
352               
353                self.exitThread()
354
Note: See TracBrowser for help on using the repository browser.