Package iceprod :: Package server :: Module rpc
[hide private]
[frames] | no frames]

Source Code for Module iceprod.server.rpc

  1  import socket, os, errno 
  2  import time 
  3  import SocketServer 
  4  import BaseHTTPServer 
  5  import SimpleHTTPServer 
  6  from SocketServer import ThreadingMixIn 
  7  import SimpleXMLRPCServer 
  8  import logging 
  9   
 10  logger = logging.getLogger('rpc') 
 11  _startuptime=time.asctime() 
 12   
13 -class SecureXMLRpcRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
14 """Secure XML-RPC request handler class. 15 16 It it very similar to SimpleXMLRPCRequestHandler but it uses HTTPS for 17 transporting XML data. 18 """
19 - def setup(self):
20 self.connection = self.request 21 self.rfile = socket._fileobject(self.request, "rb", self.rbufsize) 22 self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
23
24 - def handle_one_request(self):
25 """Handle a single HTTP request. 26 27 Overrides default method to handle broken pipes and other socket errors 28 29 """ 30 try: 31 self.raw_requestline = self.rfile.readline(65537) 32 if len(self.raw_requestline) > 65536: 33 self.requestline = '' 34 self.request_version = '' 35 self.command = '' 36 self.send_error(414) 37 return 38 if not self.raw_requestline: 39 self.close_connection = 1 40 return 41 if not self.parse_request(): 42 # An error code has been sent, just exit 43 return 44 mname = 'do_' + self.command 45 if not hasattr(self, mname): 46 self.send_error(501, "Unsupported method (%r)" % self.command) 47 return 48 method = getattr(self, mname) 49 method() 50 self.wfile.flush() #actually send the response if not already done. 51 except socket.timeout, e: 52 #a read or a write timed out. Discard this connection 53 self.log_error("Request timed out: %r", e) 54 self.close_connection = 1 55 return 56 except socket.error, e: 57 if isinstance(e.args, tuple): 58 self.log_error("errno is %d" % e[0]) 59 if e[0] == errno.EPIPE: 60 # remote peer disconnected 61 self.log_error("Detected remote disconnect") 62 elif e[0] == errno.EAGAIN: 63 # reached thread limit 64 self.log_error("Reached max thread limit") 65 else: 66 # determine and handle different error 67 self.log_error("This errno is unknown") 68 else: 69 self.log_error("socket error %r", e) 70 self.close_connection = 1 71 return 72 except IOError, e: 73 # Hmmm, Can IOError actually be raised by the socket module? 74 self.log_error("Got IOError: %r", e) 75 self.close_connection = 1 76 return
77
78 - def do_GET(self):
79 """Handles the HTTPS GET request. 80 only allow a request for the crossdomain file 81 this can be changed to support GETs of any file if needed 82 """ 83 global _startuptime 84 msg = "<head><title>IceProd</title></head>" 85 msg += "<body>" 86 msg += "<center><h1>IceProd Interface</h1></center>" 87 msg += "<center><h3>running on %s</h3></center>" % os.uname()[1] 88 msg += "<center><h3>up since %s</h3></center>" % _startuptime 89 msg += "<center>" 90 msg += "<table>" 91 try: 92 import iceprod 93 msg += "<tr><td>iceprod</td><td>%s</td></tr>" % iceprod.__version__ 94 except: pass 95 try: 96 import iceprod.server 97 msg += "<tr><td>iceprod.server</td><td>%s</td></tr>" % iceprod.server.__version__ 98 except: pass 99 try: 100 import iceprod.client 101 msg += "<tr><td>iceprod.client</td><td>%s</td></tr>" % iceprod.client.__version__ 102 except: pass 103 try: 104 import iceprod.modules 105 msg += "<tr><td>iceprod.client</td><td>%s</td></tr>" % iceprod.modules.__version__ 106 except: pass 107 msg += "</table>" 108 msg += "</center>" 109 msg += "<center>" 110 msg += "<image size=50 src=http://internal.icecube.wisc.edu/images/logo.png>" 111 msg += "</center>" 112 msg += "</body>" 113 114 #write the data to the socket along with valid HTTP headers 115 res = 'HTTP/1.0 200 OK\r\nDate: %s\r\n\r\n%s' % (self.date_time_string(),msg) 116 self.wfile.write(res) 117 self.log_request(200)
118
119 - def do_POST(self):
120 """Handles the HTTPS POST request. 121 122 It was copied out from SimpleXMLRPCServer.py and modified to shutdown 123 the socket cleanly. 124 """ 125 126 try: 127 # get arguments 128 data = self.rfile.read(int(self.headers["content-length"])) 129 # In previous versions of SimpleXMLRPCServer, _dispatch 130 # could be overridden in this class, instead of in 131 # SimpleXMLRPCDispatcher. To maintain backwards compatibility, 132 # check to see if a subclass implements _dispatch and dispatch 133 # using that method if present. 134 response = self.server._marshaled_dispatch( 135 data, getattr(self, '_dispatch', None) 136 ) 137 except: # This should only happen if the module is buggy 138 # internal error, report as HTTP server error 139 self.send_response(500) 140 self.end_headers() 141 else: 142 # got a valid XML RPC response 143 self.send_response(200) 144 self.send_header("Content-type", "text/xml") 145 self.send_header("Content-length", str(len(response))) 146 self.end_headers() 147 self.wfile.write(response) 148 149 # shut down the connection 150 self.wfile.flush() 151 self.connection.shutdown() # Modified here!
152
153 - def log_message(self, format, *args):
154 logger.debug("%s - - [%s] %s\n" % 155 (self.address_string(), 156 self.log_date_time_string(), 157 format%args))
158 159 160
161 -class SecureXMLRPCServer(BaseHTTPServer.HTTPServer,SimpleXMLRPCServer.SimpleXMLRPCDispatcher):
162 - def __init__(self, server_address=("localhost",8000), 163 HandlerClass=SecureXMLRpcRequestHandler, 164 logRequests=True,ssl_context = None):
165 """ 166 Secure Threaded XML-RPC server. 167 It it very similar to ThreadedXMLRPCServer but it uses HTTPS for 168 transporting XML data. 169 """ 170 from OpenSSL import SSL 171 172 if not ssl_context: 173 raise Exception, "you need to pass an SSL context" 174 175 self.logRequests = logRequests 176 try: 177 SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self) 178 except TypeError: 179 # An exception is raised in Python 2.5 as the prototype of the __init__ 180 # method has changed and now has 3 arguments (self, allow_none, encoding) 181 # 182 SimpleXMLRPCServer.SimpleXMLRPCDispatcher.__init__(self, False, None) 183 184 185 SocketServer.BaseServer.__init__(self, server_address, HandlerClass) 186 187 self.socket = SSL.Connection(ssl_context, socket.socket(self.address_family, self.socket_type)) 188 self.server_bind() 189 self.server_activate()
190
191 -class MyXMLRpcRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
192 - def log_message(self, format, *args):
193 logger.debug("%s - - [%s] %s\n" % 194 (self.address_string(), 195 self.log_date_time_string(), 196 format%args))
197
198 - def handle_one_request(self):
199 """Handle a single HTTP request. 200 201 Overrides default method to handle broken pipes and other socket errors 202 203 """ 204 try: 205 self.raw_requestline = self.rfile.readline(65537) 206 if len(self.raw_requestline) > 65536: 207 self.requestline = '' 208 self.request_version = '' 209 self.command = '' 210 self.send_error(414) 211 return 212 if not self.raw_requestline: 213 self.close_connection = 1 214 return 215 if not self.parse_request(): 216 # An error code has been sent, just exit 217 return 218 mname = 'do_' + self.command 219 if not hasattr(self, mname): 220 self.send_error(501, "Unsupported method (%r)" % self.command) 221 return 222 method = getattr(self, mname) 223 method() 224 self.wfile.flush() #actually send the response if not already done. 225 except socket.timeout, e: 226 #a read or a write timed out. Discard this connection 227 self.log_error("Request timed out: %r", e) 228 self.close_connection = 1 229 return 230 except socket.error, e: 231 if isinstance(e.args, tuple): 232 self.log_error("errno is %d" % e[0]) 233 if e[0] == errno.EPIPE: 234 # remote peer disconnected 235 self.log_error("Detected remote disconnect") 236 elif e[0] == errno.EAGAIN: 237 # reached thread limit 238 self.log_error("Reached max thread limit") 239 else: 240 # determine and handle different error 241 self.log_error("This errno is unknown") 242 else: 243 self.log_error("socket error %r", e) 244 self.close_connection = 1 245 return 246 except IOError, e: 247 # Hmmm, Can IOError actually be raised by the socket module? 248 self.log_error("Got IOError: %r", e) 249 self.close_connection = 1 250 return
251
252 - def do_GET(self):
253 """Handles the HTTPS GET request. 254 only allow a request for the crossdomain file 255 this can be changed to support GETs of any file if needed 256 """ 257 global _startuptime 258 msg = "<head><title>IceProd</title></head>" 259 msg += "<body>" 260 msg += "<center><h1>IceProd Interface</h1></center>" 261 msg += "<center><h3>running on %s</h3></center>" % os.uname()[1] 262 msg += "<center><h3>up since %s</h3></center>" % _startuptime 263 msg += "<center>" 264 msg += "<table>" 265 try: 266 import iceprod 267 msg += "<tr><td>iceprod</td><td>%s</td></tr>" % iceprod.__version__ 268 except: pass 269 try: 270 import iceprod.server 271 msg += "<tr><td>iceprod.server</td><td>%s</td></tr>" % iceprod.server.__version__ 272 except: pass 273 try: 274 import iceprod.client 275 msg += "<tr><td>iceprod.client</td><td>%s</td></tr>" % iceprod.client.__version__ 276 except: pass 277 try: 278 import iceprod.modules 279 msg += "<tr><td>iceprod.client</td><td>%s</td></tr>" % iceprod.modules.__version__ 280 except: pass 281 msg += "</table>" 282 msg += "</center>" 283 msg += "<center>" 284 msg += "<image size=50 src=http://internal.icecube.wisc.edu/images/logo.png>" 285 msg += "</center>" 286 msg += "</body>" 287 288 #write the data to the socket along with valid HTTP headers 289 res = 'HTTP/1.0 200 OK\r\nDate: %s\r\n\r\n%s' % (self.date_time_string(),msg) 290 self.wfile.write(res) 291 self.log_request(200)
292 293
294 -class MySimpleXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer):
295 - def __init__(self, 296 addr=("localhost",8000), 297 HandlerClass=MyXMLRpcRequestHandler, 298 logRequests=True):
299 """ 300 Secure Threaded XML-RPC server. 301 It it very similar to ThreadedXMLRPCServer but it uses HTTPS for 302 transporting XML data. 303 """ 304 self.logRequests = logRequests 305 SimpleXMLRPCServer.SimpleXMLRPCServer.__init__(self, addr, HandlerClass, logRequests)
306 307
308 -class ThreadedXMLRPCServer(ThreadingMixIn,MySimpleXMLRPCServer):
309 """"My Threaded XMLRPC Server"""
310
311 -class ThreadedSecureXMLRPCServer(ThreadingMixIn,SecureXMLRPCServer):
312 """"My Secure Threaded XMLRPC Server"""
313 314
315 -class MyCGIXMLRPCRequestHandler(SimpleXMLRPCServer.CGIXMLRPCRequestHandler):
316 - def __init__(self):
317 SimpleXMLRPCServer.CGIXMLRPCRequestHandler.__init__(self)
318 319
320 - def handle_get(self):
321 """Handles the HTTPS GET request. 322 only allow a request for the crossdomain file 323 this can be changed to support GETs of any file if needed 324 """ 325 global _startuptime 326 msg = "<head><title>IceProd</title></head>" 327 msg += "<body>" 328 msg += "<center><h1>IceProd Interface</h1></center>" 329 msg += "<center><h3>running on %s</h3></center>" % os.uname()[1] 330 msg += "<center><h3>up since %s</h3></center>" % _startuptime 331 msg += "<center>" 332 msg += "<table>" 333 try: 334 import iceprod 335 msg += "<tr><td>iceprod</td><td>%s</td></tr>" % iceprod.__version__ 336 except: pass 337 try: 338 import iceprod.server 339 msg += "<tr><td>iceprod.server</td><td>%s</td></tr>" % iceprod.server.__version__ 340 except: pass 341 try: 342 import iceprod.client 343 msg += "<tr><td>iceprod.client</td><td>%s</td></tr>" % iceprod.client.__version__ 344 except: pass 345 try: 346 import iceprod.modules 347 msg += "<tr><td>iceprod.client</td><td>%s</td></tr>" % iceprod.modules.__version__ 348 except: pass 349 msg += "</table>" 350 msg += "</center>" 351 msg += "<center>" 352 msg += "<image size=50 src=http://internal.icecube.wisc.edu/images/logo.png>" 353 msg += "</center>" 354 msg += "</body>" 355 356 print "Content-Type: text/html\n\n" 357 print msg
358