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