source: trunk/puzzlebox_thinkgear_client_twisted.py @ 353

Last change on this file since 353 was 276, checked in by sc, 10 years ago

Puzzlebox Synapse:

  • split out into separate repository from Puzzlebox Brainstorms
File size: 9.4 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# Puzzlebox - Client - ThinkGear Connector
5#
6# Copyright Puzzlebox Productions, LLC (2010)
7#
8# This code is released under the GNU Pulic License (GPL) version 2
9# For more information please refer to http://www.gnu.org/copyleft/gpl.html
10#
11# Last Update: 2010.06.22
12#
13#####################################################################
14
15import os, sys
16import simplejson as json
17
18from twisted.internet import reactor, protocol, defer
19from twisted.protocols import basic
20
21import puzzlebox_thinkgear_emulator_configuration as configuration
22
23#####################################################################
24# Globals
25#####################################################################
26
27DEBUG = 1
28
29SERVER_HOST = configuration.THINKGEAR_SERVER_HOST
30SERVER_PORT = configuration.THINKGEAR_SERVER_PORT
31
32MAX_CONNECTION_ATTEMPTS = configuration.MAX_CONNECTION_ATTEMPTS
33NO_REPLY_WAIT = configuration.NO_REPLY_WAIT
34
35THINKGEAR_DELIMITER = '\r'
36
37ENABLE_THINKGEAR_AUTHORIZATION = configuration.ENABLE_THINKGEAR_AUTHORIZATION
38AUTHORIZATION_REQUEST = configuration.THINKGEAR_AUTHORIZATION_REQUEST
39
40THINKGEAR_PARAMETERS = {"enableRawOutput": False, "format": "Json"}
41#THINKGEAR_PARAMETERS = {"enableRawOutput": True, "format": "Json"}
42#THINKGEAR_PARAMETERS = configuration.FLASH_POLICY_FILE_REQUEST
43
44#####################################################################
45# Classes
46#####################################################################
47
48class puzzlebox_thinkgear_client:
49       
50        def __init__(self, log, \
51                          server_host=SERVER_HOST, \
52                          server_port=SERVER_PORT, \
53                          DEBUG=DEBUG):
54               
55                self.log = log
56                self.DEBUG=DEBUG
57               
58                self.server_host = server_host
59                self.server_port = server_port
60                self.max_connection_attempts = MAX_CONNECTION_ATTEMPTS
61               
62                self.is_authorized = True
63       
64       
65        ##################################################################
66       
67        def authorize_and_send_parameters(self,\
68                                          thinkgear_parameters, \
69                                          authorization_request):
70               
71                if self.DEBUG:
72                        print "--> [ThinkGear Client] Sending Authorization Request:",
73                        print authorization_request
74               
75               
76                d = self.send_parameters(thinkgear_parameters, authorization_request)
77                d.addCallback(self.update_authorization)
78       
79       
80        ##################################################################
81       
82        def update_authorization(self, authorization):
83               
84                if self.DEBUG:
85                        print "--> [ThinkGear Client] Authorization:",
86                        print authorization
87               
88                self.is_authorized = authorization
89       
90       
91        ##################################################################
92       
93        def send_parameters(self, \
94                                 parameters, \
95                                 authentication=None, \
96                                 max_connection_attempts=MAX_CONNECTION_ATTEMPTS):
97               
98                self.factory = puzzlebox_thinkgear_client_factory( \
99                                  self.log, \
100                                  parameters, \
101                                  authentication, \
102                                  self.server_host, \
103                                  self.server_port, \
104                                  max_connection_attempts, \
105                                  self.DEBUG)
106               
107                reactor.connectTCP(self.server_host, self.server_port, self.factory)
108               
109                return self.factory.replyDefer
110       
111       
112        ##################################################################
113       
114        def send_parameters_and_print_response(self, parameters):
115               
116                if self.DEBUG:
117                        print "----> [ThinkGear Client] Sending:",
118                        print parameters
119               
120               
121                d = self.send_parameters(parameters)
122                d.addCallback(self.print_response)
123       
124       
125        ##################################################################
126       
127        def print_response(self, response):
128               
129                if self.DEBUG:
130                        print "--> [ThinkGear Client] Server Response:",
131                        print response
132
133
134#####################################################################
135# ThinkGear Client Protocol class
136#####################################################################
137
138class puzzlebox_thinkgear_client_protocol(basic.LineReceiver):
139       
140        delimiter = THINKGEAR_DELIMITER
141       
142        def __init__(self):
143               
144                self.DEBUG = DEBUG
145       
146       
147        ##################################################################
148       
149        def connectionMade(self):
150               
151                if self.DEBUG:
152                                        print "----> [ThinkGear Client] Connected to %s:%i" % \
153                                                        (self.factory.server_host, \
154                                                         self.factory.server_port)
155               
156               
157                if (self.factory.authentication != None):
158                        self.send_data(self.factory.authentication)
159               
160                else:
161                        self.send_data(self.factory.parameters)
162       
163       
164        ##################################################################
165       
166        def send_data(self, data):
167               
168                packet = json.dumps(data)
169               
170                if self.DEBUG:
171                        print "----> [ThinkGear Client] Sending:",
172                        print packet
173               
174               
175                self.sendLine(packet)
176               
177                #self.factory.noReply = reactor.callLater(NO_REPLY_WAIT, self.noReply)
178       
179       
180        ##################################################################
181       
182        def noReply(self):
183               
184                try:
185                        self.factory.replyDefer.callback('NO_REPLY')
186                except:
187                        if self.DEBUG:
188                                print "noReply failed to call callback"
189       
190       
191        ##################################################################
192       
193        def lineReceived(self, line):
194       
195                # Ignore blank lines
196                if not line:
197                        return
198               
199                try:
200                        data = json.loads(line)
201                except Exception, e:
202                        if self.DEBUG:
203                                print "Partial data received (or error:",
204                                print e
205                                print ")."
206                               
207                                print "line:",
208                                print line
209                               
210                                # We've received back an unrecognized response
211                                # so we'll attempt to reset the server's
212                                # parameters for JSON communication
213                                self.send_data(self.factory.parameters)
214               
215                else:
216                       
217                        if (type(data) == type({})):
218                       
219                                self.factory.process_response(data)
220                                #self.factory.replyDefer.callback(data)
221                               
222                        else:
223                                if self.DEBUG:
224                                        print "data:",
225                                        print data
226       
227       
228        ##################################################################
229       
230        def connectionLost(self, reason):
231               
232                if self.DEBUG > 1:
233                        print "Connection lost:",
234                        print reason
235       
236       
237        ##################################################################
238       
239        def connectionDone(self, reason):
240               
241                if self.DEBUG > 1:
242                        print "Connection done:",
243                        print reason
244
245
246#####################################################################
247# ThinkGear Client Factory class
248#####################################################################
249
250class puzzlebox_thinkgear_client_factory(protocol.ClientFactory):
251       
252        def __init__(self, log, \
253                     parameters, \
254                     authentication, \
255                     server_host=SERVER_HOST, \
256                     server_port=SERVER_PORT, \
257                     max_connection_attempts=MAX_CONNECTION_ATTEMPTS, \
258                     DEBUG=DEBUG):
259               
260                self.log = log
261                self.DEBUG = DEBUG
262                self.server_host = server_host
263                self.server_port = server_port
264                self.parameters = parameters
265                self.authentication = authentication
266               
267                self.max_connection_attempts = max_connection_attempts
268                self.connection_attempt = 1
269               
270                self.protocol = \
271                   puzzlebox_thinkgear_client_protocol
272               
273                self.replyDefer = defer.Deferred()
274       
275       
276        ##################################################################
277       
278        def process_response(self, response):
279               
280                if self.DEBUG:
281                        if (('rawEeg' not in response.keys()) or \
282                            (self.DEBUG > 1)):
283                                print "<-- [ThinkGear Client] Received:",
284                                print response
285               
286               
287                if response.has_key('isAuthorized'):
288                       
289                        if (response['isAuthorized'] == True):
290                                self.replyDefer.callback(True)
291                        else:
292                                self.replyDefer.callback(False)
293       
294       
295        ##################################################################
296       
297        def clientConnectionFailed(self, connector, reason):
298               
299                if self.DEBUG:
300                        print "Client failed to connect to remote component at %s:%i" % \
301                           (self.server_host, self.server_port)
302               
303                reply = 'FAILED_TO_CONNECT'
304               
305                self.connection_attempt = self.connection_attempt + 1
306               
307                if ((self.max_connection_attempts == None) or \
308                         (self.connection_attempt <= self.max_connection_attempts)):
309                       
310                        # If connection failed retry after one second
311                        reactor.callLater(1, connector.connect)
312               
313                else:
314                        if self.DEBUG:
315                                print "Maximum connection retries reached, aborting"
316                       
317                       
318                        self.replyDefer.callback(reply)
319       
320       
321        ##################################################################
322       
323        def clientConnectionLost(self, connector, reason):
324               
325                # Losing Connection is expected after data exchange is complete
326                try:
327                        self.replyDefer.callback(reason)
328                except:
329                        pass
330
331
332#####################################################################
333# Main
334#####################################################################
335
336if __name__ == '__main__':
337       
338        #log = puzzlebox_logger.puzzlebox_logger(logfile='thinkgear_client')
339        log = None
340       
341        authorization_request = AUTHORIZATION_REQUEST
342        thinkgear_parameters = THINKGEAR_PARAMETERS
343       
344        thinkgear_client = puzzlebox_thinkgear_client( \
345                    log, \
346                    server_host=SERVER_HOST, \
347                    server_port=SERVER_PORT, \
348                    DEBUG=DEBUG)
349       
350       
351        if ENABLE_THINKGEAR_AUTHORIZATION:
352                # Use ThinkGear authentication
353                reactor.callWhenRunning( \
354                        thinkgear_client.authorize_and_send_parameters, \
355                        thinkgear_parameters, \
356                        authorization_request)
357       
358        else:   
359                # Do not use ThinkGear authentication
360                authorization_request = None
361                reactor.callWhenRunning( \
362                        thinkgear_client.send_parameters, \
363                        thinkgear_parameters, \
364                        authorization_request)
365       
366       
367        reactor.run()
368
Note: See TracBrowser for help on using the repository browser.