Files
tryton/trytond/netsvc.py
T

228 lines
7.1 KiB
Python

#This file is part of Tryton. The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
import time
import threading
import SimpleXMLRPCServer, signal, sys, xmlrpclib
import SocketServer
import socket
import logging
import os
from pysocket import PySocket
import traceback
import select
import BaseHTTPServer
from trytond.protocols.sslsocket import SSLSocket
from config import CONFIG
# convert decimal to float before marshalling:
from decimal import Decimal
xmlrpclib.Marshaller.dispatch[Decimal] = \
lambda self, value, write: self.dump_long(float(value), write)
#-- XMLRPC Handler
class GenericXMLRPCRequestHandler:
def _dispatch(self, method, params):
host, port = self.client_address[:2]
logging.getLogger('web-service').info(
'connection from %s:%d' % (host, port))
try:
from protocols.dispatcher import dispatch
database_name, object_type, object_name = self.path.split("/")[-3:]
args = (database_name, params[0], params[1], object_type,
object_name, method) + params[2:]
res = dispatch(*args)
return res
except:
tb_s = ''
for line in traceback.format_exception(*sys.exc_info()):
try:
line = line.encode('utf-8', 'ignore')
except:
continue
tb_s += line
for path in sys.path:
tb_s = tb_s.replace(path, '')
if CONFIG['debug_mode']:
import pdb
traceb = sys.exc_info()[2]
pdb.post_mortem(traceb)
raise xmlrpclib.Fault(1, str(sys.exc_value) + '\n' + tb_s)
class SimpleXMLRPCRequestHandler(GenericXMLRPCRequestHandler,
SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
rpc_paths = None
class SecureXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
def setup(self):
self.connection = SSLSocket(self.request)
self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
#-- XMLRPC Server
class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn,
SimpleXMLRPCServer.SimpleXMLRPCServer):
def server_bind(self):
self.socket.setsockopt(socket.SOL_SOCKET,
socket.SO_REUSEADDR, 1)
SimpleXMLRPCServer.SimpleXMLRPCServer.server_bind(self)
class SecureThreadedXMLRPCServer(SimpleThreadedXMLRPCServer):
def __init__(self, server_address, HandlerClass, logRequests=1):
SimpleThreadedXMLRPCServer.__init__(self, server_address, HandlerClass,
logRequests)
self.socket = SSLSocket(socket.socket(self.address_family,
self.socket_type))
self.server_bind()
self.server_activate()
#-- HTPP Daemon
class HttpDaemon(threading.Thread):
def __init__(self, interface, port, secure=False):
threading.Thread.__init__(self)
self.secure = secure
self.running = False
ipv6 = False
if socket.has_ipv6:
try:
socket.getaddrinfo(interface or None, port, socket.AF_INET6)
ipv6 = True
except:
pass
if secure:
handler_class = SecureXMLRPCRequestHandler
server_class = SecureThreadedXMLRPCServer
if ipv6:
server_class = SecureThreadedXMLRPCServer6
else:
handler_class = SimpleXMLRPCRequestHandler
server_class = SimpleThreadedXMLRPCServer
if ipv6:
server_class = SimpleThreadedXMLRPCServer6
self.server = server_class((interface, port), handler_class, 0)
def stop(self):
self.running = False
if os.name != 'nt':
if hasattr(socket, 'SHUT_RDWR'):
self.server.socket.shutdown(socket.SHUT_RDWR)
else:
self.server.socket.shutdown(2)
self.server.socket.close()
def run(self):
self.server.register_introspection_functions()
self.running = True
while self.running:
self.server.handle_request()
return True
# If the server need to be run recursively
#
#signal.signal(signal.SIGALRM, self.my_handler)
#signal.alarm(6)
#while True:
# self.server.handle_request()
#signal.alarm(0) # Disable the alarm
#-- WebDAV server
class BaseThreadedHTTPServer(SocketServer.ThreadingMixIn,
BaseHTTPServer.HTTPServer):
max_children = CONFIG['max_thread']
def server_bind(self):
self.socket.setsockopt(socket.SOL_SOCKET,
socket.SO_REUSEADDR, 1)
BaseHTTPServer.HTTPServer.server_bind(self)
class SecureThreadedHTTPServer(BaseThreadedHTTPServer):
def __init__(self, server_address, HandlerClass):
BaseThreadedHTTPServer.__init__(self, server_address, HandlerClass)
self.socket = SSLSocket(socket.socket(self.address_family,
self.socket_type))
self.server_bind()
self.server_activate()
class WebDAVServerThread(threading.Thread):
def __init__(self, interface, port, secure=False):
from webdavsvc import WebDAVAuthRequestHandler, SecureWebDAVAuthRequestHandler, \
TrytonDAVInterface
threading.Thread.__init__(self)
self.secure = secure
self.running = False
ipv6 = False
if socket.has_ipv6:
try:
socket.getaddrinfo(interface or None, port, socket.AF_INET6)
ipv6 = True
except:
pass
if secure:
handler_class = SecureWebDAVAuthRequestHandler
server_class = SecureThreadedHTTPServer
if ipv6:
server_class = SecureThreadedHTTPServer6
else:
handler_class = WebDAVAuthRequestHandler
server_class = BaseThreadedHTTPServer
if ipv6:
server_class = BaseThreadedHTTPServer6
handler_class.IFACE_CLASS = TrytonDAVInterface(interface, port, secure)
self.server = server_class((interface, port), handler_class)
def stop(self):
self.running = False
if os.name != 'nt':
if hasattr(socket, 'SHUT_RDWR'):
self.server.socket.shutdown(socket.SHUT_RDWR)
else:
self.server.socket.shutdown(2)
self.server.socket.close()
def run(self):
self.running = True
while self.running:
self.server.handle_request()
return True
#-- MixIn classes --
class IPv6MixIn(object):
address_family = socket.AF_INET6
#--- IPv6 Servers
class BaseThreadedHTTPServer6(BaseThreadedHTTPServer, IPv6MixIn):
pass
class SecureThreadedHTTPServer6(SecureThreadedHTTPServer, IPv6MixIn):
pass
class SimpleThreadedXMLRPCServer6(SimpleThreadedXMLRPCServer, IPv6MixIn):
pass
#--- Secure IPv6 Servers
class SecureThreadedXMLRPCServer6(SecureThreadedXMLRPCServer, IPv6MixIn):
pass
class SecureThreadedHTTPServer6(SecureThreadedHTTPServer, IPv6MixIn):
pass