xrg has proposed merging lp:~openerp-dev/openobject-server/trunk-bug-794287-xrg 
into lp:openobject-server.

Requested reviews:
  OpenERP Core Team (openerp)
Related bugs:
  Bug #794287 in OpenERP Server: "http_server: Initial IPv6 support"
  https://bugs.launchpad.net/openobject-server/+bug/794287

For more details, see:
https://code.launchpad.net/~openerp-dev/openobject-server/trunk-bug-794287-xrg/+merge/63781
-- 
https://code.launchpad.net/~openerp-dev/openobject-server/trunk-bug-794287-xrg/+merge/63781
Your team OpenERP R&D Team is subscribed to branch 
lp:~openerp-dev/openobject-server/trunk-bug-794287-xrg.
=== modified file 'openerp/service/http_server.py'
--- openerp/service/http_server.py	2011-02-07 12:57:23 +0000
+++ openerp/service/http_server.py	2011-06-07 22:24:30 +0000
@@ -40,6 +40,7 @@
 import os
 import select
 import socket
+import re
 import xmlrpclib
 import logging
 
@@ -102,6 +103,12 @@
     def _get_next_name(self):
         self.__threadno += 1
         return 'http-client-%d' % self.__threadno
+
+class Threaded6HTTPServer(ThreadedHTTPServer):
+    """A variant of ThreadedHTTPServer for IPv6
+    """
+    address_family = socket.AF_INET6
+
 class HttpLogHandler:
     """ helper class for uniform log handling
     Please define self._logger at each class that is derived from this
@@ -136,17 +143,18 @@
 
 class BaseHttpDaemon(threading.Thread, netsvc.Server):
     _RealProto = '??'
+    _IsSecure = False
 
-    def __init__(self, interface, port, handler):
-        threading.Thread.__init__(self, name='%sDaemon-%d'%(self._RealProto, port))
+    def __init__(self, address, handler, server_class=ThreadedHTTPServer):
+        threading.Thread.__init__(self, name='%sDaemon-%d'%(self._RealProto, address[1]))
         netsvc.Server.__init__(self)
-        self.__port = port
-        self.__interface = interface
+        self.__address = address
 
         try:
-            self.server = ThreadedHTTPServer((interface, port), handler, proto=self._RealProto)
+            self.server = server_class(address, handler, proto=self._RealProto)
             self.server.vdirs = []
             self.server.logRequests = True
+            interface, port = address[:2]
             self.server.timeout = self._busywait_timeout
             logging.getLogger("web-services").info(
                         "starting %s service at %s port %d" %
@@ -208,57 +216,121 @@
 class HttpDaemon(BaseHttpDaemon):
     _RealProto = 'HTTP'
     def __init__(self, interface, port):
-        super(HttpDaemon, self).__init__(interface, port,
+        super(HttpDaemon, self).__init__(address=(interface, port),
                                          handler=MultiHandler2)
 
 class HttpSDaemon(BaseHttpDaemon):
     _RealProto = 'HTTPS'
+    _IsSecure = True
     def __init__(self, interface, port):
         try:
-            super(HttpSDaemon, self).__init__(interface, port,
+            super(HttpSDaemon, self).__init__(address=(interface, port),
                                               handler=SecureMultiHandler2)
         except SSLError, e:
             logging.getLogger('httpsd').exception( \
                         "Can not load the certificate and/or the private key files")
             raise
 
-httpd = None
-httpsd = None
+class Http6Daemon(BaseHttpDaemon):
+    _RealProto = 'HTTP6'
+    def __init__(self, interface, port):
+        super(Http6Daemon, self).__init__(address=(interface, port, 0, 0),
+                                         handler=MultiHandler2,
+                                         server_class=Threaded6HTTPServer)
+        self.daemon = True
+
+class Http6SDaemon(BaseHttpDaemon):
+    _RealProto = 'HTTP6S'
+    def __init__(self, interface, port):
+        try:
+            super(Http6SDaemon, self).__init__(address=(interface, port),
+                                              handler=SecureMultiHandler2,
+                                              server_class=Threaded6HTTPServer)
+            self.daemon = True
+
+        except SSLError, e:
+            logging.getLogger('httpsd').exception( \
+                        "Can not load the certificate and/or the private key files")
+            raise
+
+http_daemons = []
 
 def init_servers():
-    global httpd, httpsd
+    global http_daemons
+    ipv4_re = re.compile('^([0-9]{1,3}(?:\.(?:[0-9]{1,3})){3})(?::(\d{1,5}))?$')
+    ipv6_re = re.compile('^\[([0-9a-f:]+)\](?::(\d{1,5}))?$')
+    
+    ipv6_missing = False
     if tools.config.get('xmlrpc'):
-        httpd = HttpDaemon(tools.config.get('xmlrpc_interface', ''),
-                           int(tools.config.get('xmlrpc_port', 8069)))
+        ifaces = tools.config.get('xmlrpc_interface', '')
+        if not ifaces:
+            ifaces = '0.0.0.0' # By default, IPv4 only
+        ifaces = map(str.strip, ifaces.split(','))
+        base_port = tools.config.get('xmlrpc_port',8069)
+        for iface in ifaces:
+            m = ipv4_re.match(iface)
+            if m:
+                httpd = HttpDaemon( m.group(1), int(m.group(2) or base_port))
+                http_daemons.append(httpd)
+                continue
+            m = ipv6_re.match(iface)
+            if m:
+                if not socket.has_ipv6:
+                    ipv6_missing = True
+                    continue
+                httpd = Http6Daemon( m.group(1), int(m.group(2) or base_port))
+                http_daemons.append(httpd)
+                continue
+            logging.getLogger('httpd').error("Cannot understand address \"%s\" to launch http daemon on!", iface)
 
     if tools.config.get('xmlrpcs'):
-        httpsd = HttpSDaemon(tools.config.get('xmlrpcs_interface', ''),
-                             int(tools.config.get('xmlrpcs_port', 8071)))
-
-def reg_http_service(hts, secure_only = False):
+        ifaces = tools.config.get('xmlrpcs_interface', '')
+        if not ifaces:
+            ifaces = '0.0.0.0' # By default, IPv4 only
+        ifaces = map(str.strip, ifaces.split(','))
+        base_port = tools.config.get('xmlrpcs_port', 8071)
+        for iface in ifaces:
+            m = ipv4_re.match(iface)
+            if m:
+                httpd = HttpSDaemon( m.group(1), int(m.group(2) or base_port))
+                http_daemons.append(httpd)
+                continue
+            m = ipv6_re.match(iface)
+            if m:
+                if not socket.has_ipv6:
+                    ipv6_missing = True
+                    continue
+                httpd = Http6SDaemon( m.group(1), int(m.group(2) or base_port))
+                http_daemons.append(httpd)
+                continue
+            logging.getLogger('httpd').error("Cannot understand address \"%s\" to launch http daemon on!", iface)
+
+    if ipv6_missing:
+        logging.getLogger('http6d').warning("HTTPd servers for IPv6 specified, but not supported at this platform.")
+
+def reg_http_service(hts, secure_only=False):
     """ Register some handler to httpd.
         hts must be an HTTPDir
     """
-    global httpd, httpsd
-
-    if httpd and not secure_only:
+    global http_daemons
+
+    if not http_daemons:
+        logging.getLogger('httpd').warning("No httpd available to register service %s" % hts.path)
+        return False
+
+    for httpd in http_daemons:
+        if secure_only and not httpd._IsSecure:
+            continue
         httpd.append_svc(hts)
-
-    if httpsd:
-        httpsd.append_svc(hts)
-
-    if (not httpd) and (not httpsd):
-        logging.getLogger('httpd').warning("No httpd available to register service %s" % hts.path)
-    return
+    return True
 
 def list_http_services(protocol=None):
-    global httpd, httpsd
-    if httpd and (protocol == 'http' or protocol == None):
+    global http_daemons
+    for httpd in http_daemons:
+        if protocol is not None and protocol != httpd._RealProto.lower():
+            continue
         return httpd.list_services()
-    elif httpsd and (protocol == 'https' or protocol == None):
-        return httpsd.list_services()
-    else:
-        raise Exception("Incorrect protocol or no http services")
+    raise Exception("Incorrect protocol or no http services")
 
 import SimpleXMLRPCServer
 class XMLRPCRequestHandler(netsvc.OpenERPDispatcher,FixSendError,HttpLogHandler,SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
@@ -288,14 +360,14 @@
     if tools.config.get('xmlrpc', False):
         # Example of http file serving:
         # reg_http_service(HTTPDir('/test/',HTTPHandler))
-        reg_http_service(HTTPDir('/xmlrpc/', XMLRPCRequestHandler))
-        logging.getLogger("web-services").info("Registered XML-RPC over HTTP")
+        if reg_http_service(HTTPDir('/xmlrpc/', XMLRPCRequestHandler)):
+            logging.getLogger("web-services").info("Registered XML-RPC over HTTP")
 
     if tools.config.get('xmlrpcs', False) \
             and not tools.config.get('xmlrpc', False):
         # only register at the secure server
-        reg_http_service(HTTPDir('/xmlrpc/', XMLRPCRequestHandler), True)
-        logging.getLogger("web-services").info("Registered XML-RPC over HTTPS only")
+        if reg_http_service(HTTPDir('/xmlrpc/', XMLRPCRequestHandler), True):
+            logging.getLogger("web-services").info("Registered XML-RPC over HTTPS only")
 
 class StaticHTTPHandler(HttpLogHandler, FixSendError, HttpOptions, HTTPHandler):
     _logger = logging.getLogger('httpd')

=== modified file 'openerp/service/websrv_lib.py'
--- openerp/service/websrv_lib.py	2011-01-18 23:50:33 +0000
+++ openerp/service/websrv_lib.py	2011-06-07 22:24:30 +0000
@@ -135,6 +135,9 @@
         if request.startswith(self.path):
             return self.path
         return False
+    
+    def __repr__(self):
+        return "<http %r on %s>" %(self.handler, self.path)
 
 class noconnection(object):
     """ a class to use instead of the real connection
@@ -465,7 +468,15 @@
                                 ssl_version=ssl.PROTOCOL_SSLv23)
             self.rfile = self.connection.makefile('rb', self.rbufsize)
             self.wfile = self.connection.makefile('wb', self.wbufsize)
-            self.log_message("Secure %s connection from %s",self.connection.cipher(),self.client_address)
+            ciph_str = 'N/A'
+            addr_str = '?'
+            if self.connection.cipher():
+                ciph_str = self.connection.cipher()[0]
+            if self.client_address and len(self.client_address) == 4:
+                addr_str = '[%s]:%s' % self.client_address[:2]
+            elif self.client_address:
+                addr_str = '%s:%s' % self.client_address
+            self.log_message("Secure %s connection from %s",ciph_str,addr_str)
         except Exception:
             self.request.shutdown(socket.SHUT_RDWR)
             raise

_______________________________________________
Mailing list: https://launchpad.net/~openerp-dev-gtk
Post to     : [email protected]
Unsubscribe : https://launchpad.net/~openerp-dev-gtk
More help   : https://help.launchpad.net/ListHelp

Reply via email to