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
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 """
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
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
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()
51 except socket.timeout, e:
52
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
61 self.log_error("Detected remote disconnect")
62 elif e[0] == errno.EAGAIN:
63
64 self.log_error("Reached max thread limit")
65 else:
66
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
74 self.log_error("Got IOError: %r", e)
75 self.close_connection = 1
76 return
77
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
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
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
128 data = self.rfile.read(int(self.headers["content-length"]))
129
130
131
132
133
134 response = self.server._marshaled_dispatch(
135 data, getattr(self, '_dispatch', None)
136 )
137 except:
138
139 self.send_response(500)
140 self.end_headers()
141 else:
142
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
150 self.wfile.flush()
151 self.connection.shutdown()
152
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):
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
180
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
193 logger.debug("%s - - [%s] %s\n" %
194 (self.address_string(),
195 self.log_date_time_string(),
196 format%args))
197
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
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()
225 except socket.timeout, e:
226
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
235 self.log_error("Detected remote disconnect")
236 elif e[0] == errno.EAGAIN:
237
238 self.log_error("Reached max thread limit")
239 else:
240
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
248 self.log_error("Got IOError: %r", e)
249 self.close_connection = 1
250 return
251
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
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
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
309 """"My Threaded XMLRPC Server"""
310
312 """"My Secure Threaded XMLRPC Server"""
313
314
317 SimpleXMLRPCServer.CGIXMLRPCRequestHandler.__init__(self)
318
319
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