source: rc/puzzlebox_brainstorms_client.py @ 25

Last change on this file since 25 was 25, checked in by sc, 12 years ago

server:

  • major cleanup, unecessary code pruned

client_interface_button:

  • whitespace cleanup

client:

  • major cleanup, unecessary code pruned

client_interface:

  • major cleanup, unecessary code pruned

client_interface_component:

  • whitespace cleanup
File size: 7.5 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# Puzzlebox - Brainstorms - Client
5#
6# Copyright Puzzlebox Productions, LLC (2010)
7#
8# Portions of this code have been previously
9# released under the GNU Pulic License (GPL) version 2
10# and is Copyright Steven M. Castellotti (2010)
11# For more information please refer to http://www.gnu.org/copyleft/gpl.htm
12#
13# Last Update: 2010.02.02
14#
15#####################################################################
16
17import os, sys
18import cPickle as pickle
19
20from twisted.internet import reactor, protocol, defer
21
22import puzzlebox_brainstorms_configuration as configuration
23#import puzzlebox_logger
24
25#####################################################################
26# Globals
27#####################################################################
28
29DEBUG = 1
30
31SERVER_HOST = configuration.SERVER_HOST
32SERVER_PORT = configuration.SERVER_PORT
33
34MAX_CONNECTION_ATTEMPTS = configuration.MAX_CONNECTION_ATTEMPTS
35NO_REPLY_WAIT = configuration.NO_REPLY_WAIT
36
37#####################################################################
38# Classes
39#####################################################################
40
41class puzzlebox_brainstorms_client:
42       
43        def __init__(self, log, \
44                          server_host, \
45                          server_port, \
46                          max_connection_attempts = MAX_CONNECTION_ATTEMPTS):
47               
48                self.log = log
49                self.server_host = server_host
50                self.server_port = server_port
51                #self.service_name = service_name
52                #self.target_name = target_name
53                self.max_connection_attempts = max_connection_attempts
54       
55       
56        ##################################################################
57       
58        def send_command(self, \
59                         command, \
60                         max_connection_attempts=MAX_CONNECTION_ATTEMPTS):
61               
62                factory = puzzlebox_brainstorms_client_send_command_factory(self.log, \
63                                                       command, \
64                                                       self.server_host, \
65                                                       self.server_port, \
66                                                       max_connection_attempts, \
67                                                       self.DEBUG)
68               
69                reactor.connectTCP(self.server_host, self.server_port, factory)
70               
71                return factory.replyDefer
72
73
74#####################################################################
75# Client Protocol class
76#####################################################################
77
78class puzzlebox_brainstorms_client_send_command_protocol(protocol.Protocol):
79       
80        def __init__(self):
81               
82                self.DEBUG = DEBUG
83                self.data_chunk = ""
84       
85       
86        ##################################################################
87       
88        def connectionMade(self):
89               
90                data = pickle.dumps(self.factory.command)
91                self.transport.write(data)
92               
93                self.factory.noReply = reactor.callLater(NO_REPLY_WAIT, self.noReply)
94       
95       
96        ##################################################################
97       
98        def noReply(self):
99               
100                try:
101                        self.factory.replyDefer.callback('NO_REPLY')
102                except:
103                        if self.DEBUG:
104                                print "noReply failed to call callback"
105                        #self.factory.log.error("noReply failed to call callback")
106               
107                self.transport.loseConnection()
108       
109       
110        ##################################################################
111       
112        def dataReceived(self, data):
113               
114                try:
115                        self.factory.noReply.cancel()
116                except:
117                        self.factory.log.error("dataReceived after noReply triggered (or cancelled)")
118               
119                self.data_chunk += data
120               
121                try:
122                        reply = pickle.loads(self.data_chunk)
123                except Exception, e:
124                        self.factory.log.error("Partial data received (or error: %s)." % e)
125                else:
126                        self.data_chunk = ""
127                       
128                        try:
129                                self.factory.replyDefer.callback(reply)
130                        except:
131                                if self.DEBUG:
132                                        print "dataReceived failed to call callback"
133                                #self.factory.log.error("dataReceived failed to call callback")
134                                pass
135                       
136                        self.transport.loseConnection()
137
138
139#####################################################################
140# Client Factory class
141#####################################################################
142
143class puzzlebox_brainstorms_client_send_command_factory(protocol.ClientFactory):
144               
145        def __init__(self, log, \
146                     command, \
147                     server_host=SERVER_HOST, \
148                     server_port=SERVER_PORT, \
149                     max_connection_attempts=MAX_CONNECTION_ATTEMPTS, \
150                     DEBUG=DEBUG):
151               
152                self.log = log
153                self.DEBUG = DEBUG
154                self.server_host = server_host
155                self.server_port = server_port
156                self.command = command
157               
158                self.max_connection_attempts = max_connection_attempts
159                self.connection_attempt = 1
160               
161                self.protocol = \
162                   puzzlebox_brainstorms_client_send_command_protocol
163               
164                self.replyDefer = defer.Deferred()
165       
166       
167        ##################################################################
168       
169        def clientConnectionFailed(self, connector, reason):
170               
171                if self.DEBUG:
172                        print "Client failed to connect to remote component at %s:%i" % \
173                           (self.server_host, self.server_port)
174               
175                reply='FAILED_TO_CONNECT'
176               
177                self.connection_attempt = self.connection_attempt + 1
178               
179                if ((self.max_connection_attempts == None) or \
180                         (self.connection_attempt <= self.max_connection_attempts)):
181               
182                        # If connection failed retry after one second
183                        reactor.callLater(1, connector.connect)
184               
185                else:
186                        if self.DEBUG:
187                                print "Maximum connection retries reached, aborting"
188                       
189                       
190                        self.replyDefer.callback(reply)
191       
192       
193        ##################################################################
194       
195        def clientConnectionLost(self, connector, reason):
196               
197                # Losing Connection is expected after data exchange is complete
198                try:
199                        self.replyDefer.callback(reason)
200                except:
201                        pass
202
203
204#####################################################################
205# Command line class
206#####################################################################
207
208class puzzlebox_brainstorms_client_command_line(puzzlebox_brainstorms_client):
209       
210        def __init__(self, log, \
211                          command_parameters, \
212                          server_host=SERVER_HOST, \
213                          server_port=SERVER_PORT, \
214                          DEBUG=DEBUG):
215               
216                self.log = log
217                self.DEBUG=DEBUG
218               
219                self.command_parameters = command_parameters
220                self.server_host = SERVER_HOST
221                self.server_port = SERVER_PORT
222                self.max_connection_attempts = MAX_CONNECTION_ATTEMPTS
223       
224       
225        ##################################################################
226       
227        def execute_command_line(self):
228               
229                (command) = self.parse_command_line(self.command_parameters)
230               
231                d = self.send_command(command)
232                d.addCallback(self.print_response_and_stop)
233       
234       
235        ##################################################################
236       
237        def print_response_and_stop(self, response):
238               
239                if self.DEBUG:
240                        print "---> [Client] Server Response:",
241                        print response
242               
243                try:
244                        reactor.stop()
245                except:
246                        print "ERROR: Can't stop reactor that isn't running."
247       
248       
249        ##################################################################
250       
251        def parse_command_line(self, command_parameters):
252               
253                try:
254                        command = command_parameters[0]
255                except:
256                        command = None
257               
258               
259                return(command)
260
261
262#####################################################################
263# Main
264#####################################################################
265
266if __name__ == '__main__':
267       
268        #log = puzzlebox_logger.puzzlebox_logger(logfile='client')
269        log = None
270       
271        command_parameters = sys.argv[1:]
272       
273        #log.info("Command parameters: %s" % command_parameters)
274       
275        client = puzzlebox_brainstorms_client_command_line(log, \
276                                                           command_parameters, \
277                                                           server_host=SERVER_HOST, \
278                                                           server_port=SERVER_PORT, \
279                                                           DEBUG=DEBUG)
280        reactor.callWhenRunning(client.execute_command_line)
281        reactor.run()
282
Note: See TracBrowser for help on using the repository browser.