1 | # |
||
2 | # Copyright 2001 - 2016 Ludek Smid [http://www.ospace.net/] |
||
3 | # |
||
4 | # This file is part of Outer Space. |
||
5 | # |
||
6 | # Outer Space is free software; you can redistribute it and/or modify |
||
7 | # it under the terms of the GNU General Public License as published by |
||
8 | # the Free Software Foundation; either version 2 of the License, or |
||
9 | # (at your option) any later version. |
||
10 | # |
||
11 | # Outer Space is distributed in the hope that it will be useful, |
||
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
14 | # GNU General Public License for more details. |
||
15 | # |
||
16 | # You should have received a copy of the GNU General Public License |
||
17 | # along with Outer Space; if not, write to the Free Software |
||
18 | # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
||
19 | # |
||
20 | |||
21 | import traceback |
||
22 | import time |
||
23 | import os |
||
24 | import log |
||
25 | import ige |
||
26 | import ige.version |
||
27 | from medusa import igerpc_handler, http_server, asyncore, logger, status_handler |
||
28 | from medusa import filesys, default_handler, counter, producers, xmlrpc_handler |
||
29 | |||
30 | callMap = {} |
||
31 | objMap = {} |
||
32 | registeredGames = {} |
||
33 | |||
34 | running = 0 |
||
35 | |||
36 | def ping(obj): |
||
37 | return True, None |
||
38 | |||
39 | ## Handlers |
||
40 | def versionHandler(obj): |
||
41 | result = {} |
||
42 | result.update(ige.version.version) |
||
43 | result["clientURLs"] = ige.version.clientURLs |
||
44 | return result, None |
||
45 | |||
46 | def getRegisteredGamesHandler(obj): |
||
47 | return registeredGames, None |
||
48 | |||
49 | ## IGE RPC medusa handler |
||
50 | class igerpc(igerpc_handler.igerpc_handler): |
||
51 | |||
52 | def __init__(self): |
||
53 | igerpc_handler.igerpc_handler.__init__(self) |
||
54 | self.seriousExcCounter = counter.counter() |
||
55 | |||
56 | def call(self, packet): |
||
57 | global callMap |
||
58 | global running |
||
59 | |||
60 | try: |
||
61 | params = [packet.sid] |
||
62 | params.extend(packet.params) |
||
63 | packet.result, packet.messages = callMap[intern(packet.method)](*params) |
||
64 | packet.method = None |
||
65 | packet.params = None |
||
66 | return packet |
||
67 | except ige.NoAccountException, e: |
||
68 | raise e |
||
69 | except ige.GameException, e: |
||
70 | raise e |
||
71 | except ige.SecurityException, e: |
||
72 | raise e |
||
73 | except ige.CreatePlayerException, e: |
||
74 | raise e |
||
75 | except ige.ServerStatusException, e: |
||
76 | raise e |
||
77 | except ige.NoSuchObjectException, e: |
||
78 | raise e |
||
79 | except asyncore.ExitNow, e: |
||
80 | raise e |
||
81 | except Exception, e: |
||
82 | log.warning('Cannot complete RPC call') |
||
83 | self.seriousExcCounter.increment() |
||
84 | raise e |
||
85 | |||
86 | View Code Duplication | def status (self): |
|
0 ignored issues
–
show
Duplication
introduced
by
![]() |
|||
87 | return producers.simple_producer ( |
||
88 | '<li>%s' % status_handler.html_repr (self) |
||
89 | + '<ul>' |
||
90 | + ' <li><b>Total Commands:</b> %s' % self.commandCounter |
||
91 | + ' <li><b>Completed:</b> %s' % self.completedCounter |
||
92 | + ' <li><b>Serious Exceptions:</b> %s' % self.seriousExcCounter |
||
93 | + ' <li><b>Total Exceptions:</b> %s' % self.exceptionsCounter |
||
94 | + '</ul>' |
||
95 | ) |
||
96 | |||
97 | ## XML RPC medusa handler |
||
98 | class xmlrpc(xmlrpc_handler.xmlrpc_handler): |
||
99 | |||
100 | IDENT = 'XML RPC Request Handler' |
||
101 | |||
102 | def __init__(self): |
||
103 | xmlrpc_handler.xmlrpc_handler.__init__(self) |
||
104 | self.commandCounter = counter.counter() |
||
105 | self.completedCounter = counter.counter() |
||
106 | self.exceptionsCounter = counter.counter() |
||
107 | self.seriousExcCounter = counter.counter() |
||
108 | |||
109 | def call(self, method, params): |
||
110 | log.debug('CALL', method, params) |
||
111 | try: |
||
112 | instanceName, methodName = method.split('.') |
||
113 | return getattr(objMap[instanceName], 'rpc_%s' % methodName)(*params) |
||
114 | #except ige.NoAccountException, e: |
||
115 | # raise e |
||
116 | #except ige.GameException, e: |
||
117 | # raise e |
||
118 | #except ige.SecurityException, e: |
||
119 | # raise e |
||
120 | #except ige.ServerStatusException, e: |
||
121 | # raise e |
||
122 | except asyncore.ExitNow, e: |
||
123 | raise e |
||
124 | except Exception, e: |
||
125 | log.warning('Cannot complete RPC call') |
||
126 | self.seriousExcCounter.increment() |
||
127 | raise e |
||
128 | |||
129 | View Code Duplication | def status (self): |
|
0 ignored issues
–
show
|
|||
130 | return producers.simple_producer ( |
||
131 | '<li>%s' % status_handler.html_repr (self) |
||
132 | + '<ul>' |
||
133 | + ' <li><b>Total Commands:</b> %s' % self.commandCounter |
||
134 | + ' <li><b>Completed:</b> %s' % self.completedCounter |
||
135 | + ' <li><b>Serious Exceptions:</b> %s' % self.seriousExcCounter |
||
136 | + ' <li><b>Total Exceptions:</b> %s' % self.exceptionsCounter |
||
137 | + '</ul>' |
||
138 | ) |
||
139 | |||
140 | def __repr__ (self): |
||
141 | return '<%s at %x>' % ( |
||
142 | self.IDENT, |
||
143 | id (self) |
||
144 | ) |
||
145 | |||
146 | ## Public interface |
||
147 | def init(clientMngr, bookingMngr): |
||
148 | global callMap |
||
149 | |||
150 | callMap['ping'] = ping |
||
151 | callMap['login'] = clientMngr.login |
||
152 | callMap['logout'] = clientMngr.logout |
||
153 | callMap['hello'] = clientMngr.hello |
||
154 | callMap['createAccount'] = clientMngr.createAccount |
||
155 | callMap['changePassword'] = clientMngr.changePassword |
||
156 | callMap['getAccountData'] = clientMngr.getAccountData |
||
157 | callMap['shutdown'] = clientMngr.serverShutdown |
||
158 | callMap['cleanupSessions'] = clientMngr.cleanupSessions |
||
159 | callMap['exportAccounts'] = clientMngr.exportAccounts |
||
160 | callMap['getVersion'] = versionHandler |
||
161 | callMap['getRegisteredGames'] = getRegisteredGamesHandler |
||
162 | callMap['getBookingAnswers'] = bookingMngr.get_booking_answers |
||
163 | callMap['getBookingOffers'] = bookingMngr.get_booking_offers |
||
164 | callMap['toggleBooking'] = bookingMngr.toggle_booking |
||
165 | callMap['createPrivateBooking'] = bookingMngr.create_private_booking |
||
166 | callMap['deletePrivateBooking'] = bookingMngr.delete_private_booking |
||
167 | |||
168 | def register(game): |
||
169 | global callMap |
||
170 | |||
171 | callMap[game.gameID + '.selectPlayer'] = game.selectPlayer |
||
172 | callMap[game.gameID + '.execute'] = game.execute |
||
173 | callMap[game.gameID + '.createNewPlayer'] = game.createNewPlayer |
||
174 | callMap[game.gameID + '.takeOverAIPlayer'] = game.takeOverAIPlayer |
||
175 | callMap[game.gameID + '.takeOverPirate'] = game.takeOverPirate |
||
176 | callMap[game.gameID + '.getActivePositions'] = game.getActivePositions |
||
177 | callMap[game.gameID + '.getStartingPositions'] = game.getStartingPositions |
||
178 | callMap[game.gameID + '.getTurnData'] = game.getTurnData |
||
179 | callMap[game.gameID + '.turnFinished'] = game.turnFinished |
||
180 | callMap[game.gameID + '.processTurn'] = game.processTurn |
||
181 | callMap[game.gameID + '.backup'] = game.backup |
||
182 | callMap[game.gameID + '.commitDatabases'] = game.commitDatabases |
||
183 | |||
184 | global registeredGames |
||
185 | registeredGames[game.gameID] = game.gameName |
||
186 | |||
187 | |||
188 | def xmlrpcPublish(name, obj): |
||
189 | objMap[name] = obj |
||
190 | |||
191 | class emptyLogger: |
||
192 | |||
193 | def log(self, data): |
||
194 | pass |
||
195 | #log.debug("MEDUSA", data) |
||
196 | |||
197 | def start(configDir): |
||
198 | global running |
||
199 | |||
200 | # install signal handler for SIGTERM |
||
201 | import signal |
||
202 | |||
203 | def signalHandler(signum, frame): |
||
204 | global running |
||
205 | |||
206 | log.message("RECEIVED SIGNAL", signum) |
||
207 | running = 0 |
||
208 | |||
209 | signal.signal(signal.SIGTERM, signalHandler) |
||
210 | |||
211 | # create server |
||
212 | logger = emptyLogger() |
||
213 | server = http_server.http_server('', 9080, logger_object = logger) |
||
214 | |||
215 | fsys = filesys.os_filesystem (os.path.join(configDir, 'website')) |
||
216 | default = default_handler.default_handler (fsys) |
||
217 | server.install_handler(default) |
||
218 | |||
219 | handler = igerpc() |
||
220 | server.install_handler(handler) |
||
221 | |||
222 | handler = xmlrpc() |
||
223 | server.install_handler(handler) |
||
224 | |||
225 | status = status_handler.status_extension([server]) |
||
226 | server.install_handler(status) |
||
227 | |||
228 | running = 1 |
||
229 | |||
230 | # get poll function |
||
231 | import select |
||
232 | if hasattr(select, "poll"): |
||
233 | poll = asyncore.poll3 |
||
234 | else: |
||
235 | poll = asyncore.poll |
||
236 | |||
237 | # main loop |
||
238 | try: |
||
239 | while running: |
||
240 | poll(timeout = 1.0) |
||
241 | except KeyboardInterrupt: |
||
242 | log.message("KeyboardInterrupt") |
||
243 | except asyncore.ExitNow: |
||
244 | log.message("ExitNow") |
||
245 | except: |
||
246 | traceback.print_exc() |
||
247 |