Completed
Push — master ( 79c35a...3e3ee6 )
by Marek
16s queued 14s
created

ige.RPCServer.igerpc.call()   C

Complexity

Conditions 9

Size

Total Lines 29
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 28
nop 2
dl 0
loc 29
rs 6.6666
c 0
b 0
f 0
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
## Handlers
37
def versionHandler(obj):
38
    result = {}
39
    result.update(ige.version.version)
40
    result["clientURLs"] = ige.version.clientURLs
41
    return result, None
42
43
def getRegisteredGamesHandler(obj):
44
    return registeredGames, None
45
46
## IGE RPC medusa handler
47
class igerpc(igerpc_handler.igerpc_handler):
48
49
    def __init__(self):
50
        igerpc_handler.igerpc_handler.__init__(self)
51
        self.seriousExcCounter = counter.counter()
52
53
    def call(self, packet):
54
        global callMap
55
        global running
56
57
        try:
58
            params = [packet.sid]
59
            params.extend(packet.params)
60
            packet.result, packet.messages = callMap[intern(packet.method)](*params)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable intern does not seem to be defined.
Loading history...
61
            packet.method = None
62
            packet.params = None
63
            return packet
64
        except ige.NoAccountException, e:
65
            raise e
66
        except ige.GameException, e:
67
            raise e
68
        except ige.SecurityException, e:
69
            raise e
70
        except ige.CreatePlayerException, e:
71
            raise e
72
        except ige.ServerStatusException, e:
73
            raise e
74
        except ige.NoSuchObjectException, e:
75
            raise e
76
        except asyncore.ExitNow, e:
77
            raise e
78
        except Exception, e:
79
            log.warning('Cannot complete RPC call')
80
            self.seriousExcCounter.increment()
81
            raise e
82
83 View Code Duplication
    def status (self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
84
        return producers.simple_producer (
85
            '<li>%s' % status_handler.html_repr (self)
86
            + '<ul>'
87
            + '  <li><b>Total Commands:</b> %s' % self.commandCounter
88
            + '  <li><b>Completed:</b> %s' % self.completedCounter
89
            + '  <li><b>Serious Exceptions:</b> %s' % self.seriousExcCounter
90
            + '  <li><b>Total Exceptions:</b> %s' % self.exceptionsCounter
91
            + '</ul>'
92
            )
93
94
## XML RPC medusa handler
95
class xmlrpc(xmlrpc_handler.xmlrpc_handler):
96
97
    IDENT = 'XML RPC Request Handler'
98
99
    def __init__(self):
100
        xmlrpc_handler.xmlrpc_handler.__init__(self)
101
        self.commandCounter = counter.counter()
102
        self.completedCounter = counter.counter()
103
        self.exceptionsCounter = counter.counter()
104
        self.seriousExcCounter = counter.counter()
105
106
    def call(self, method, params):
107
        log.debug('CALL', method, params)
108
        try:
109
            instanceName, methodName = method.split('.')
110
            return getattr(objMap[instanceName], 'rpc_%s' % methodName)(*params)
111
            #except ige.NoAccountException, e:
112
            #    raise e
113
            #except ige.GameException, e:
114
            #    raise e
115
            #except ige.SecurityException, e:
116
            #    raise e
117
            #except ige.ServerStatusException, e:
118
            #    raise e
119
        except asyncore.ExitNow, e:
120
            raise e
121
        except Exception, e:
122
            log.warning('Cannot complete RPC call')
123
            self.seriousExcCounter.increment()
124
            raise e
125
126 View Code Duplication
    def status (self):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
127
        return producers.simple_producer (
128
            '<li>%s' % status_handler.html_repr (self)
129
            + '<ul>'
130
            + '  <li><b>Total Commands:</b> %s' % self.commandCounter
131
            + '  <li><b>Completed:</b> %s' % self.completedCounter
132
            + '  <li><b>Serious Exceptions:</b> %s' % self.seriousExcCounter
133
            + '  <li><b>Total Exceptions:</b> %s' % self.exceptionsCounter
134
            + '</ul>'
135
            )
136
137
    def __repr__ (self):
138
        return '<%s at %x>' % (
139
            self.IDENT,
140
            id (self)
141
            )
142
143
## Public interface
144
def init(clientMngr, bookingMngr):
145
    global callMap
146
147
    callMap['login'] = clientMngr.login
148
    callMap['logout'] = clientMngr.logout
149
    callMap['hello'] = clientMngr.hello
150
    callMap['createAccount'] = clientMngr.createAccount
151
    callMap['changePassword'] = clientMngr.changePassword
152
    callMap['getAccountData'] = clientMngr.getAccountData
153
    callMap['shutdown'] = clientMngr.serverShutdown
154
    callMap['cleanupSessions'] = clientMngr.cleanupSessions
155
    callMap['exportAccounts'] = clientMngr.exportAccounts
156
    callMap['getVersion'] = versionHandler
157
    callMap['getRegisteredGames'] = getRegisteredGamesHandler
158
    callMap['getBookingAnswers'] = bookingMngr.get_booking_answers
159
    callMap['getBookingOffers'] = bookingMngr.get_booking_offers
160
    callMap['toggleBooking'] = bookingMngr.toggle_booking
161
    callMap['createPrivateBooking'] = bookingMngr.create_private_booking
162
    callMap['deletePrivateBooking'] = bookingMngr.delete_private_booking
163
164
def register(game):
165
    global callMap
166
167
    callMap[game.gameID + '.selectPlayer'] = game.selectPlayer
168
    callMap[game.gameID + '.execute'] = game.execute
169
    callMap[game.gameID + '.createNewPlayer'] = game.createNewPlayer
170
    callMap[game.gameID + '.takeOverAIPlayer'] = game.takeOverAIPlayer
171
    callMap[game.gameID + '.takeOverPirate'] = game.takeOverPirate
172
    callMap[game.gameID + '.getActivePositions'] = game.getActivePositions
173
    callMap[game.gameID + '.getStartingPositions'] = game.getStartingPositions
174
    callMap[game.gameID + '.getTurnData'] = game.getTurnData
175
    callMap[game.gameID + '.turnFinished'] = game.turnFinished
176
    callMap[game.gameID + '.processTurn'] = game.processTurn
177
    callMap[game.gameID + '.backup'] = game.backup
178
    callMap[game.gameID + '.commitDatabases'] = game.commitDatabases
179
180
    global registeredGames
181
    registeredGames[game.gameID] = game.gameName
182
183
184
def xmlrpcPublish(name, obj):
185
    objMap[name] = obj
186
187
class emptyLogger:
188
189
    def log(self, data):
190
        pass
191
        #log.debug("MEDUSA", data)
192
193
def start(configDir):
194
    global running
195
196
    # install signal handler for SIGTERM
197
    import signal
198
199
    def signalHandler(signum, frame):
200
        global running
201
202
        log.message("RECEIVED SIGNAL", signum)
203
        running = 0
204
205
    signal.signal(signal.SIGTERM, signalHandler)
206
207
    # create server
208
    logger = emptyLogger()
209
    server = http_server.http_server('', 9080, logger_object = logger)
210
211
    fsys = filesys.os_filesystem (os.path.join(configDir, 'website'))
212
    default = default_handler.default_handler (fsys)
213
    server.install_handler(default)
214
215
    handler = igerpc()
216
    server.install_handler(handler)
217
218
    handler = xmlrpc()
219
    server.install_handler(handler)
220
221
    status = status_handler.status_extension([server])
222
    server.install_handler(status)
223
224
    running = 1
225
226
    # get poll function
227
    import select
228
    if hasattr(select, "poll"):
229
        poll = asyncore.poll3
230
    else:
231
        poll = asyncore.poll
232
233
    # main loop
234
    try:
235
        while running:
236
            poll(timeout = 1.0)
237
    except KeyboardInterrupt:
238
        log.message("KeyboardInterrupt")
239
    except asyncore.ExitNow:
240
        log.message("ExitNow")
241
    except:
242
        traceback.print_exc()
243