extras-buildsys/common AuthedXMLRPCServer.py, 1.2, 1.3 XMLRPCServerProxy.py, 1.3, 1.4

Daniel Williams (dcbw) fedora-extras-commits at redhat.com
Sun Jul 10 03:44:39 UTC 2005


Author: dcbw

Update of /cvs/fedora/extras-buildsys/common
In directory cvs-int.fedora.redhat.com:/tmp/cvs-serv19340/common

Modified Files:
	AuthedXMLRPCServer.py XMLRPCServerProxy.py 
Log Message:
2005-07-09  Dan Williams <dcbw at redhat.com>

    * Rework the authorization framework so we don't need to
        subclass/override subclass so much stuff

    * Make the specfile Python version independent




Index: AuthedXMLRPCServer.py
===================================================================
RCS file: /cvs/fedora/extras-buildsys/common/AuthedXMLRPCServer.py,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- AuthedXMLRPCServer.py	6 Jul 2005 21:20:55 -0000	1.2
+++ AuthedXMLRPCServer.py	10 Jul 2005 03:44:36 -0000	1.3
@@ -12,8 +12,8 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 #
-# Copyright 2005 Konstantin Ryabitsev <icon at phy.duke.edu>
-# Modified by Dan Williams <dcbw at redhat.com>
+# Copyright 2005 Dan Williams <dcbw at redhat.com> and Red Hat, Inc.
+
 
 import os, sys
 import socket
@@ -22,6 +22,44 @@
 import xmlrpclib
 import SimpleXMLRPCServer
 import SSLCommon
+import threading
+
+
+
+"""
+So we need a way of getting data from the RequestHandler instance, which
+is unique to each request, into the actual handler instance that we've registered.
+
+To do this without overriding a bunch of member functions, we have a global
+dict of data that maps authorization info to a particular thread, since each
+request is handled in its own thread.  Therefore, the handler instance can
+access the data that our request handler has set.
+
+"""
+
+__authinfos_lock = threading.Lock()
+__authinfos = {}
+
+
+def _add_authinfo(authinfo):
+    __authinfos_lock.acquire()
+    __authinfos[threading.currentThread()] = authinfo
+    __authinfos_lock.release()
+
+def get_authinfo():
+    i = None
+    __authinfos_lock.acquire()
+    try:
+        i = __authinfos[threading.currentThread()]
+    except KeyError:
+        pass
+    __authinfos_lock.release()
+    return i
+
+def _del_authinfo():
+    __authinfos_lock.acquire()
+    del __authinfos[threading.currentThread()]
+    __authinfos_lock.release()
 
 
 class AuthedSimpleXMLRPCRequestHandler(SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
@@ -32,50 +70,10 @@
     protocol_version = "HTTP/1.1"
 
     def do_POST(self):
-        """
-        See documentation on SimpleXMLRPCRequestHandler.  Modifications
-        include the ability to pass through local request-specific data,
-        and removal of code to deal with historical _dispatch methods.
-        """
-
-        if 0:
-            # ONLY FOR DEBUGGING, so we can see exceptions on the console
-            # get arguments
-            data = self.rfile.read(int(self.headers["content-length"]))
-            authinfo = self.server.get_authinfo(self.request, self.client_address)
-            response = self.server._marshaled_dispatch(data, authinfo)
-
-            # got a valid XML RPC response
-            self.send_response(200)
-            self.send_header("Content-type", "text/xml")
-            self.send_header("Content-length", str(len(response)))
-            self.end_headers()
-            self.wfile.write(response)
-
-            # shut down the connection
-            self.wfile.flush()
-            self.connection.shutdown(1)
-        else:
-            try:
-                # get arguments
-                data = self.rfile.read(int(self.headers["content-length"]))
-                authinfo = self.server.get_authinfo(self.request, self.client_address)
-                response = self.server._marshaled_dispatch(data, authinfo)
-            except: # This should only happen if the module is buggy
-                # internal error, report as HTTP server error
-                self.send_response(500)
-                self.end_headers()
-            else:
-                # got a valid XML RPC response
-                self.send_response(200)
-                self.send_header("Content-type", "text/xml")
-                self.send_header("Content-length", str(len(response)))
-                self.end_headers()
-                self.wfile.write(response)
-
-                # shut down the connection
-                self.wfile.flush()
-                self.connection.shutdown(1)
+        authinfo = self.server.get_authinfo(self.request, self.client_address)
+        _add_authinfo(authinfo)
+        SimpleXMLRPCServer.SimpleXMLRPCRequestHandler.do_POST(self)
+        _del_authinfo()
 
 
 class BaseAuthedXMLRPCServer:
@@ -92,68 +90,6 @@
             return self.authinfo_callback(request, client_address)
         return None
 
-    def verify_request(self, request, client_address):
-        return True
-
-    def _marshaled_dispatch(self, data, authinfo):
-        """
-        Allow the ability to pass request-dependent objects into
-        the handler instance.
-        """
-        params, method = xmlrpclib.loads(data)
-
-        # generate response
-        try:
-            response = self._dispatch(authinfo, method, params)
-            # wrap response in a singleton tuple
-            response = (response,)
-            response = xmlrpclib.dumps(response, methodresponse=1)
-        except xmlrpclib.Fault, fault:
-            response = xmlrpclib.dumps(fault)
-        except:
-            # report exception back to server
-            response = xmlrpclib.dumps(
-                xmlrpclib.Fault(1, "%s:%s" % (sys.exc_type, sys.exc_value))
-                )
-
-        return response
-
-    def _dispatch(self, authinfo, method, params):
-        """
-        Allow the ability to pass request-dependent objects into
-        the handler instance.
-        """
-        func = None
-        try:
-            # check to see if a matching function has been registered
-            func = self.funcs[method]
-        except KeyError:
-            if self.instance is not None:
-                # call instance method directly
-                try:
-                    func = self.lcl_resolve_dotted_attribute(method)
-                except AttributeError:
-                    pass
-
-        if func is not None:
-            # Only pass authinfo into Instance if we have are set
-            # up to get authinfo
-            if self.authinfo_callback is not None:
-                return func(authinfo, *params)
-            else:
-                return func(*params)
-        else:
-            raise Exception('method "%s" is not supported' % method)
-
-    def lcl_resolve_dotted_attribute(self, method):
-        pyver = sys.version_info[:3]
-        if pyver <= (2, 3, 4):
-            return SimpleXMLRPCServer.resolve_dotted_attribute(
-                self.instance, method)
-        elif pyver > (2, 3, 4):
-            return SimpleXMLRPCServer.resolve_dotted_attribute(
-                self.instance, method, self.allow_dotted_names)
-
 
 class AuthedSSLXMLRPCServer(BaseAuthedXMLRPCServer, SSLCommon.PlgBaseSSLServer, SimpleXMLRPCServer.SimpleXMLRPCServer):
     """ Extension to allow more fine-tuned SSL handling """
@@ -176,8 +112,24 @@
 
 class ReqHandler:
     def ping(self):
+        authinfo = get_authinfo()
+        print "AUTHINFO: %s" % authinfo
         return "pong"
 
+class TestServer(AuthedSSLXMLRPCServer):
+    """
+    SSL XMLRPC server that authenticates clients based on their certificate.
+    """
+
+    def __init__(self, address, certs):
+        AuthedSSLXMLRPCServer.__init__(self, address, self.auth_cb, certs)
+
+    def auth_cb(self, request, client_address):
+        import random
+        peer_cert = request.get_peer_certificate()
+        email = peer_cert.get_subject().countryName
+        return "AUTH: %s - %d" % (email, random.randint(1, 100))
+
 
 if __name__ == '__main__':
     if len(sys.argv) < 4:
@@ -190,7 +142,7 @@
     certs['peer_ca_cert'] = sys.argv[3]
 
     print "Starting the server."
-    server = AuthedSSLXMLRPCServer(('localhost', 8886), None, certs)
+    server = TestServer(('localhost', 8886), certs)
     h = ReqHandler()
     server.register_instance(h)
     server.serve_forever()


Index: XMLRPCServerProxy.py
===================================================================
RCS file: /cvs/fedora/extras-buildsys/common/XMLRPCServerProxy.py,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- XMLRPCServerProxy.py	9 Jul 2005 21:44:23 -0000	1.3
+++ XMLRPCServerProxy.py	10 Jul 2005 03:44:36 -0000	1.4
@@ -49,6 +49,32 @@
 # Testing stuff
 ###########################################################
 
+
+import threading
+import time
+import random
+
+client_start = False
+
+_lock = threading.Lock()
+
+class TestClient(threading.Thread):
+    def __init__(self, certs):
+        self.server = PlgXMLRPCServerProxy("https://127.0.0.1:8886", certs)
+        threading.Thread.__init__(self)
+
+    def run(self):
+        while not client_start:
+            time.sleep(0.05)
+        i = 0
+        while i < 5:
+#            _lock.acquire()
+            print self.server.ping()
+            time.sleep(0.05)
+#            _lock.release()
+            i = i + 1
+
+
 if __name__ == '__main__':
     if len(sys.argv) < 4:
         print "Usage: python XMLRPCServerProxy.py key_and_cert ca_cert peer_ca_cert"
@@ -59,5 +85,19 @@
     certs['ca_cert'] = sys.argv[2]
     certs['peer_ca_cert'] = sys.argv[3]
 
-    s = XMLRPCServerProxy("https://127.0.0.1:8886", certs)
-    print s.ping()
+    i = 100
+    while i > 0:
+        t = TestClient(certs)
+        print "Created thread %d." % i
+        t.start()
+        i = i - 1
+
+    time.sleep(3)
+    print "Unleashing threads."
+    client_start = True
+    while True:
+        try:
+            time.sleep(0.25)
+        except KeyboardInterrupt:
+            os._exit(0)
+




More information about the scm-commits mailing list