Index: preprover_py/server.py
===================================================================
--- preprover_py/server.py	(revision 5a71baca801f1a21555fa8f443c27396ef2bad2b)
+++ preprover_py/server.py	(revision 5a71baca801f1a21555fa8f443c27396ef2bad2b)
@@ -0,0 +1,101 @@
+#!/usr/bin/python
+
+from BaseHTTPServer import BaseHTTPRequestHandler
+
+from M2Crypto import SSL
+from M2Crypto.SSL.SSLServer import ForkingSSLServer
+import xmlrpclib
+
+# The SSL server here is based on the implementation described at
+# http://www.xml.com/pub/a/ws/2004/01/20/salz.html
+
+# Turn off the matching of hostname to certificate ID
+SSL.Connection.clientPostConnectionCheck = None
+
+class server(ForkingSSLServer):
+    """
+    Interface the fedd services to the XMLRPC and SOAP interfaces
+    """
+    def __init__(self, ME, ssl_ctx):
+        """
+        Create an SSL server that handles the transport in handler using the
+        credentials in ssl_ctx.  ME is the host port pair on which to bind.
+        """
+
+        ForkingSSLServer.__init__(self, ME, xmlrpc_handler, ssl_ctx)
+
+#    def handle_error(self, request=None, address=None):
+#        """
+#        The default SSLServer prints a stack trace here.  This is a little
+#        friendlier.
+#        """
+#        if request or address:
+#            print "[partialprover] Error on incoming connection: %s %s" % \
+#                    (request or "", address or "")
+#        else:
+#            print "[partialprover] Error on incoming connection " + \
+#                    "(Likely SSL error)"
+
+class xmlrpc_handler(BaseHTTPRequestHandler):
+    """
+    Standard connection between XMLRPC and the fedd services in impl.
+
+    Much of this is boilerplate from 
+    http://www.xml.com/pub/a/ws/2004/01/20/salz.html
+    """
+    server_version = "libabac/0.1 " + BaseHTTPRequestHandler.server_version
+
+    def send_xml(self, text, code=200):
+        """Send an XML document as reply"""
+        self.send_response(code)
+        self.send_header('Content-type', 'text/xml; charset="utf-8"')
+        self.send_header('Content-Length', str(len(text)))
+        self.end_headers()
+        self.wfile.write(text)
+        self.wfile.flush()
+        # Make sure to close the socket when we're done
+        self.request.socket.close()
+
+    def do_POST(self):
+        """Treat an HTTP POST request as an XMLRPC service call"""
+        # NB: XMLRPC faults are not HTTP errors, so the code is always 200,
+        # unless an HTTP error occurs, which we don't handle.
+
+        resp = None
+        data = None
+        method = None
+        cl = int(self.headers['content-length'])
+        data = self.rfile.read(cl)
+
+        try:
+            params, method = xmlrpclib.loads(data)
+        except xmlrpclib.ResponseError:
+            data = xmlrpclib.dumps(xmlrpclib.Fault("Client",
+                "Malformed request"), methodresponse=True)
+
+        if method != None:
+            try:
+                resp = self.xmlrpc_dispatch(method, params,
+                            fedid(cert=self.request.get_peer_cert()))
+                data = xmlrpclib.dumps((resp,), encoding='UTF-8',
+                        methodresponse=True)
+            except xmlrpclib.Fault, f:
+                data = xmlrpclib.dumps(f, methodresponse=True)
+                resp = None
+
+        self.send_xml(data)
+
+    def xmlrpc_dispatch(self, method, req, fid):
+        """
+        The connection to the implementation, using the  method maps
+
+        The implementation provides a mapping from XMLRPC method name to the
+        method in the implementation that provides the service.
+        """
+        if self.server.xmlrpc_methods.has_key(method):
+            try:
+                return self.server.xmlrpc_methods[method](req, fid)
+            except service_error, e:
+                raise xmlrpclib.Fault(e.code_string(), e.desc)
+        else:
+            raise xmlrpclib.Fault(100, "Unknown method: %s" % method)
