2009-10-20 10:52:23 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
2008-06-16 07:24:04 +00:00
|
|
|
##############################################################################
|
|
|
|
#
|
2008-12-14 16:46:47 +00:00
|
|
|
# OpenERP, Open Source Management Solution
|
2009-01-04 22:13:29 +00:00
|
|
|
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
|
2008-12-19 15:10:11 +00:00
|
|
|
# The refactoring about the OpenSSL support come from Tryton
|
2009-01-04 22:13:29 +00:00
|
|
|
# Copyright (C) 2007-2009 Cédric Krier.
|
|
|
|
# Copyright (C) 2007-2009 Bertrand Chenal.
|
2008-12-19 15:10:11 +00:00
|
|
|
# Copyright (C) 2008 B2CK SPRL.
|
2008-06-16 07:24:04 +00:00
|
|
|
#
|
2008-11-03 18:27:16 +00:00
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
2008-06-16 07:24:04 +00:00
|
|
|
#
|
2008-11-03 18:27:16 +00:00
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
2008-06-16 07:24:04 +00:00
|
|
|
#
|
2008-11-03 18:27:16 +00:00
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2008-06-16 07:24:04 +00:00
|
|
|
#
|
2008-11-03 18:27:16 +00:00
|
|
|
##############################################################################
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2008-12-18 18:13:41 +00:00
|
|
|
import SimpleXMLRPCServer
|
2006-12-07 13:41:40 +00:00
|
|
|
import SocketServer
|
|
|
|
import logging
|
2008-11-25 10:35:00 +00:00
|
|
|
import logging.handlers
|
2006-12-22 13:07:53 +00:00
|
|
|
import os
|
2008-12-18 23:54:33 +00:00
|
|
|
import signal
|
|
|
|
import socket
|
|
|
|
import sys
|
|
|
|
import threading
|
|
|
|
import time
|
|
|
|
import xmlrpclib
|
2008-12-22 23:04:18 +00:00
|
|
|
import release
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2009-01-05 18:55:20 +00:00
|
|
|
SERVICES = {}
|
|
|
|
GROUPS = {}
|
2008-08-12 14:44:56 +00:00
|
|
|
|
2006-12-07 13:41:40 +00:00
|
|
|
class Service(object):
|
2008-07-22 14:24:36 +00:00
|
|
|
def __init__(self, name, audience=''):
|
2009-01-05 18:55:20 +00:00
|
|
|
SERVICES[name] = self
|
2008-08-12 14:44:56 +00:00
|
|
|
self.__name = name
|
2009-01-05 18:55:20 +00:00
|
|
|
self._methods = {}
|
2008-08-12 14:44:56 +00:00
|
|
|
|
|
|
|
def joinGroup(self, name):
|
2009-01-05 18:55:20 +00:00
|
|
|
GROUPS.setdefault(name, {})[self.__name] = self
|
2008-07-22 14:24:36 +00:00
|
|
|
|
2009-01-05 18:55:20 +00:00
|
|
|
def exportMethod(self, method):
|
|
|
|
if callable(method):
|
|
|
|
self._methods[method.__name__] = method
|
2008-07-22 14:24:36 +00:00
|
|
|
|
|
|
|
def abortResponse(self, error, description, origin, details):
|
|
|
|
if not tools.config['debug_mode']:
|
2008-08-12 14:44:56 +00:00
|
|
|
raise Exception("%s -- %s\n\n%s"%(origin, description, details))
|
2008-07-22 14:24:36 +00:00
|
|
|
else:
|
|
|
|
raise
|
|
|
|
|
2006-12-07 13:41:40 +00:00
|
|
|
class LocalService(Service):
|
2008-07-22 14:24:36 +00:00
|
|
|
def __init__(self, name):
|
2008-08-12 14:44:56 +00:00
|
|
|
self.__name = name
|
2008-11-27 08:27:20 +00:00
|
|
|
try:
|
2009-01-05 18:55:20 +00:00
|
|
|
self._service = SERVICES[name]
|
|
|
|
for method_name, method_definition in self._service._methods.items():
|
|
|
|
setattr(self, method_name, method_definition)
|
2008-11-27 08:27:20 +00:00
|
|
|
except KeyError, keyError:
|
|
|
|
Logger().notifyChannel('module', LOG_ERROR, 'This service does not exists: %s' % (str(keyError),) )
|
|
|
|
raise
|
2009-01-05 19:14:56 +00:00
|
|
|
def __call__(self, method, *params):
|
|
|
|
return getattr(self, method)(*params)
|
2008-11-27 08:27:20 +00:00
|
|
|
|
2007-06-07 12:00:30 +00:00
|
|
|
def service_exist(name):
|
2009-01-05 18:55:20 +00:00
|
|
|
return SERVICES.get(name, False)
|
2007-06-07 12:00:30 +00:00
|
|
|
|
2008-12-22 23:04:18 +00:00
|
|
|
LOG_NOTSET = 'notset'
|
2008-12-18 10:10:43 +00:00
|
|
|
LOG_DEBUG_RPC = 'debug_rpc'
|
2008-08-12 14:44:56 +00:00
|
|
|
LOG_DEBUG = 'debug'
|
|
|
|
LOG_INFO = 'info'
|
|
|
|
LOG_WARNING = 'warn'
|
|
|
|
LOG_ERROR = 'error'
|
|
|
|
LOG_CRITICAL = 'critical'
|
|
|
|
|
2008-12-18 10:10:43 +00:00
|
|
|
# add new log level below DEBUG
|
|
|
|
logging.DEBUG_RPC = logging.DEBUG - 1
|
2006-12-07 13:41:40 +00:00
|
|
|
|
|
|
|
def init_logger():
|
2008-07-22 14:24:36 +00:00
|
|
|
import os
|
2009-02-04 17:27:00 +00:00
|
|
|
from tools.translate import resetlocale
|
2009-02-05 13:40:49 +00:00
|
|
|
resetlocale()
|
2008-07-22 14:24:36 +00:00
|
|
|
|
2008-12-22 23:04:18 +00:00
|
|
|
logger = logging.getLogger()
|
2008-12-29 10:24:51 +00:00
|
|
|
# create a format for log messages and dates
|
2009-02-05 13:40:49 +00:00
|
|
|
formatter = logging.Formatter('[%(asctime)s] %(levelname)s:%(name)s:%(message)s')
|
2009-07-07 10:02:07 +00:00
|
|
|
|
2009-01-30 16:55:51 +00:00
|
|
|
logging_to_stdout = False
|
2008-12-26 15:05:51 +00:00
|
|
|
if tools.config['syslog']:
|
2008-12-22 23:04:18 +00:00
|
|
|
# SysLog Handler
|
|
|
|
if os.name == 'nt':
|
2008-12-29 10:24:51 +00:00
|
|
|
handler = logging.handlers.NTEventLogHandler("%s %s" %
|
2008-12-22 23:04:18 +00:00
|
|
|
(release.description,
|
|
|
|
release.version))
|
|
|
|
else:
|
2008-12-29 10:24:51 +00:00
|
|
|
handler = logging.handlers.SysLogHandler('/dev/log')
|
2009-02-05 13:40:49 +00:00
|
|
|
formatter = logging.Formatter("%s %s" % (release.description, release.version) + ':%(levelname)s:%(name)s:%(message)s')
|
2008-12-22 23:04:18 +00:00
|
|
|
|
2008-12-29 10:24:51 +00:00
|
|
|
elif tools.config['logfile']:
|
2008-12-22 23:04:18 +00:00
|
|
|
# LogFile Handler
|
2008-12-26 15:05:51 +00:00
|
|
|
logf = tools.config['logfile']
|
2008-07-22 14:24:36 +00:00
|
|
|
try:
|
2008-11-25 10:35:00 +00:00
|
|
|
dirname = os.path.dirname(logf)
|
2008-12-12 00:28:15 +00:00
|
|
|
if dirname and not os.path.isdir(dirname):
|
|
|
|
os.makedirs(dirname)
|
2008-09-18 14:02:05 +00:00
|
|
|
handler = logging.handlers.TimedRotatingFileHandler(logf,'D',1,30)
|
2008-12-12 00:28:15 +00:00
|
|
|
except Exception, ex:
|
2009-01-30 16:55:51 +00:00
|
|
|
sys.stderr.write("ERROR: couldn't create the logfile directory. Logging to the standard output.\n")
|
2009-07-07 10:02:07 +00:00
|
|
|
handler = logging.StreamHandler(sys.stdout)
|
2009-01-30 16:55:51 +00:00
|
|
|
logging_to_stdout = True
|
2008-07-22 14:24:36 +00:00
|
|
|
else:
|
2008-12-22 23:04:18 +00:00
|
|
|
# Normal Handler on standard output
|
2008-07-22 14:24:36 +00:00
|
|
|
handler = logging.StreamHandler(sys.stdout)
|
2009-01-30 16:55:51 +00:00
|
|
|
logging_to_stdout = True
|
2008-07-22 14:24:36 +00:00
|
|
|
|
|
|
|
|
|
|
|
# tell the handler to use this format
|
|
|
|
handler.setFormatter(formatter)
|
|
|
|
|
|
|
|
# add the handler to the root logger
|
2008-12-22 23:04:18 +00:00
|
|
|
logger.addHandler(handler)
|
2008-12-26 15:05:51 +00:00
|
|
|
logger.setLevel(tools.config['log_level'] or '0')
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2009-01-30 16:55:51 +00:00
|
|
|
if logging_to_stdout and os.name != 'nt':
|
2008-09-12 08:45:21 +00:00
|
|
|
# change color of level names
|
|
|
|
# uses of ANSI color codes
|
|
|
|
# see http://pueblo.sourceforge.net/doc/manual/ansi_color_codes.html
|
|
|
|
# maybe use http://code.activestate.com/recipes/574451/
|
|
|
|
colors = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', None, 'default']
|
|
|
|
foreground = lambda f: 30 + colors.index(f)
|
|
|
|
background = lambda f: 40 + colors.index(f)
|
2008-09-18 14:02:05 +00:00
|
|
|
|
2008-09-12 08:45:21 +00:00
|
|
|
mapping = {
|
2008-12-18 10:10:43 +00:00
|
|
|
'DEBUG_RPC': ('blue', 'white'),
|
2008-09-12 08:45:21 +00:00
|
|
|
'DEBUG': ('blue', 'default'),
|
|
|
|
'INFO': ('green', 'default'),
|
|
|
|
'WARNING': ('yellow', 'default'),
|
|
|
|
'ERROR': ('red', 'default'),
|
|
|
|
'CRITICAL': ('white', 'red'),
|
|
|
|
}
|
|
|
|
|
|
|
|
for level, (fg, bg) in mapping.items():
|
|
|
|
msg = "\x1b[%dm\x1b[%dm%s\x1b[0m" % (foreground(fg), background(bg), level)
|
|
|
|
logging.addLevelName(getattr(logging, level), msg)
|
|
|
|
|
2006-12-07 13:41:40 +00:00
|
|
|
|
|
|
|
class Logger(object):
|
2009-07-07 10:02:07 +00:00
|
|
|
|
2008-08-12 14:44:56 +00:00
|
|
|
def notifyChannel(self, name, level, msg):
|
2009-07-07 10:02:07 +00:00
|
|
|
from service.web_services import common
|
|
|
|
|
2009-02-05 13:40:49 +00:00
|
|
|
log = logging.getLogger(tools.ustr(name))
|
2008-12-18 10:10:43 +00:00
|
|
|
|
|
|
|
if level == LOG_DEBUG_RPC and not hasattr(log, level):
|
|
|
|
fct = lambda msg, *args, **kwargs: log.log(logging.DEBUG_RPC, msg, *args, **kwargs)
|
|
|
|
setattr(log, LOG_DEBUG_RPC, fct)
|
|
|
|
|
2008-12-10 21:23:54 +00:00
|
|
|
level_method = getattr(log, level)
|
|
|
|
|
2009-01-07 18:44:27 +00:00
|
|
|
if isinstance(msg, Exception):
|
|
|
|
msg = tools.exception_to_unicode(msg)
|
|
|
|
|
2009-08-14 14:09:48 +00:00
|
|
|
msg = tools.ustr(msg).strip()
|
|
|
|
|
2009-07-07 10:02:07 +00:00
|
|
|
if level in (LOG_ERROR,LOG_CRITICAL):
|
2009-09-09 14:54:11 +00:00
|
|
|
msg = common().get_server_environment() + '\n' + msg
|
2009-07-07 10:02:07 +00:00
|
|
|
|
2009-08-14 14:09:48 +00:00
|
|
|
result = msg.split('\n')
|
2008-12-10 21:23:54 +00:00
|
|
|
if len(result)>1:
|
|
|
|
for idx, s in enumerate(result):
|
2008-12-29 10:24:51 +00:00
|
|
|
level_method('[%02d]: %s' % (idx+1, s,))
|
2008-12-10 21:23:54 +00:00
|
|
|
elif result:
|
2008-12-29 10:24:51 +00:00
|
|
|
level_method(result[0])
|
2008-08-12 14:44:56 +00:00
|
|
|
|
2008-12-30 17:58:25 +00:00
|
|
|
def shutdown(self):
|
|
|
|
logging.shutdown()
|
|
|
|
|
2008-12-26 15:05:51 +00:00
|
|
|
import tools
|
2008-12-08 14:03:42 +00:00
|
|
|
init_logger()
|
2006-12-07 13:41:40 +00:00
|
|
|
|
|
|
|
class Agent(object):
|
2009-03-04 23:53:28 +00:00
|
|
|
_timers = {}
|
2008-07-22 14:24:36 +00:00
|
|
|
_logger = Logger()
|
|
|
|
|
2009-03-04 23:53:28 +00:00
|
|
|
def setAlarm(self, fn, dt, db_name, *args, **kwargs):
|
2008-07-22 14:24:36 +00:00
|
|
|
wait = dt - time.time()
|
|
|
|
if wait > 0:
|
2009-08-21 12:03:07 +00:00
|
|
|
self._logger.notifyChannel('timers', LOG_DEBUG, "Job scheduled in %s seconds for %s.%s" % (wait, fn.im_class.__name__, fn.func_name))
|
2008-07-22 14:24:36 +00:00
|
|
|
timer = threading.Timer(wait, fn, args, kwargs)
|
|
|
|
timer.start()
|
2009-03-04 23:53:28 +00:00
|
|
|
self._timers.setdefault(db_name, []).append(timer)
|
2008-07-22 14:24:36 +00:00
|
|
|
|
2009-03-04 23:53:28 +00:00
|
|
|
for db in self._timers:
|
|
|
|
for timer in self._timers[db]:
|
|
|
|
if not timer.isAlive():
|
|
|
|
self._timers[db].remove(timer)
|
2009-07-07 10:02:07 +00:00
|
|
|
|
2009-03-04 23:53:28 +00:00
|
|
|
@classmethod
|
|
|
|
def cancel(cls, db_name):
|
|
|
|
"""Cancel all timers for a given database. If None passed, all timers are cancelled"""
|
|
|
|
for db in cls._timers:
|
|
|
|
if db_name is None or db == db_name:
|
|
|
|
for timer in cls._timers[db]:
|
|
|
|
timer.cancel()
|
2009-07-07 10:02:07 +00:00
|
|
|
|
2009-03-04 23:53:28 +00:00
|
|
|
@classmethod
|
2008-07-22 14:24:36 +00:00
|
|
|
def quit(cls):
|
2009-03-04 23:53:28 +00:00
|
|
|
cls.cancel(None)
|
2008-12-30 17:30:46 +00:00
|
|
|
|
|
|
|
import traceback
|
|
|
|
|
2006-12-07 13:41:40 +00:00
|
|
|
class xmlrpc(object):
|
2008-07-22 14:24:36 +00:00
|
|
|
class RpcGateway(object):
|
|
|
|
def __init__(self, name):
|
2008-08-12 14:44:56 +00:00
|
|
|
self.name = name
|
|
|
|
|
2009-01-05 18:55:20 +00:00
|
|
|
class OpenERPDispatcherException(Exception):
|
|
|
|
def __init__(self, exception, traceback):
|
|
|
|
self.exception = exception
|
|
|
|
self.traceback = traceback
|
|
|
|
|
|
|
|
class OpenERPDispatcher:
|
2008-12-18 18:13:41 +00:00
|
|
|
def log(self, title, msg):
|
|
|
|
from pprint import pformat
|
2009-01-05 18:55:20 +00:00
|
|
|
Logger().notifyChannel('%s' % title, LOG_DEBUG_RPC, pformat(msg))
|
2008-12-18 18:13:41 +00:00
|
|
|
|
2009-01-05 18:55:20 +00:00
|
|
|
def dispatch(self, service_name, method, params):
|
2009-08-28 16:50:27 +00:00
|
|
|
if service_name not in GROUPS['web-services']:
|
|
|
|
raise Exception('AccessDenied')
|
2008-07-22 14:24:36 +00:00
|
|
|
try:
|
2009-01-05 18:55:20 +00:00
|
|
|
self.log('service', service_name)
|
2008-12-18 18:13:41 +00:00
|
|
|
self.log('method', method)
|
|
|
|
self.log('params', params)
|
2009-01-05 19:14:56 +00:00
|
|
|
result = LocalService(service_name)(method, *params)
|
2009-01-05 18:55:20 +00:00
|
|
|
self.log('result', result)
|
|
|
|
return result
|
2008-07-22 14:24:36 +00:00
|
|
|
except Exception, e:
|
2009-01-09 09:12:01 +00:00
|
|
|
self.log('exception', tools.exception_to_unicode(e))
|
2009-01-15 13:34:04 +00:00
|
|
|
if hasattr(e, 'traceback'):
|
|
|
|
tb = e.traceback
|
|
|
|
else:
|
|
|
|
tb = sys.exc_info()
|
2008-12-30 17:30:46 +00:00
|
|
|
tb_s = "".join(traceback.format_exception(*tb))
|
2008-07-22 14:24:36 +00:00
|
|
|
if tools.config['debug_mode']:
|
|
|
|
import pdb
|
2008-12-30 17:30:46 +00:00
|
|
|
pdb.post_mortem(tb[2])
|
2009-01-05 18:55:20 +00:00
|
|
|
raise OpenERPDispatcherException(e, tb_s)
|
|
|
|
|
|
|
|
class GenericXMLRPCRequestHandler(OpenERPDispatcher):
|
|
|
|
def _dispatch(self, method, params):
|
|
|
|
try:
|
|
|
|
service_name = self.path.split("/")[-1]
|
|
|
|
return self.dispatch(service_name, method, params)
|
|
|
|
except OpenERPDispatcherException, e:
|
2009-01-07 18:44:27 +00:00
|
|
|
raise xmlrpclib.Fault(tools.exception_to_unicode(e.exception), e.traceback)
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2008-12-18 23:54:33 +00:00
|
|
|
class SSLSocket(object):
|
|
|
|
def __init__(self, socket):
|
|
|
|
if not hasattr(socket, 'sock_shutdown'):
|
|
|
|
from OpenSSL import SSL
|
|
|
|
ctx = SSL.Context(SSL.SSLv23_METHOD)
|
2008-12-22 23:35:28 +00:00
|
|
|
ctx.use_privatekey_file(tools.config['secure_pkey_file'])
|
|
|
|
ctx.use_certificate_file(tools.config['secure_cert_file'])
|
2008-12-18 23:54:33 +00:00
|
|
|
self.socket = SSL.Connection(ctx, socket)
|
|
|
|
else:
|
|
|
|
self.socket = socket
|
|
|
|
|
|
|
|
def shutdown(self, how):
|
|
|
|
return self.socket.sock_shutdown(how)
|
2008-12-18 19:13:14 +00:00
|
|
|
|
2008-12-18 23:54:33 +00:00
|
|
|
def __getattr__(self, name):
|
|
|
|
return getattr(self.socket, name)
|
|
|
|
|
|
|
|
class SimpleXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
|
2009-08-28 16:18:02 +00:00
|
|
|
rpc_paths = map(lambda s: '/xmlrpc/%s' % s, GROUPS.get('web-services', {}).keys())
|
2008-12-18 23:54:33 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
|
|
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()
|
2008-12-18 19:13:14 +00:00
|
|
|
|
2007-02-03 22:58:57 +00:00
|
|
|
class HttpDaemon(threading.Thread):
|
2008-08-12 14:44:56 +00:00
|
|
|
def __init__(self, interface, port, secure=False):
|
2008-07-22 14:24:36 +00:00
|
|
|
threading.Thread.__init__(self)
|
2008-08-12 14:44:56 +00:00
|
|
|
self.__port = port
|
|
|
|
self.__interface = interface
|
2008-12-18 20:28:01 +00:00
|
|
|
self.secure = bool(secure)
|
2008-12-18 23:54:33 +00:00
|
|
|
handler_class = (SimpleXMLRPCRequestHandler, SecureXMLRPCRequestHandler)[self.secure]
|
|
|
|
server_class = (SimpleThreadedXMLRPCServer, SecureThreadedXMLRPCServer)[self.secure]
|
2008-12-19 10:55:28 +00:00
|
|
|
|
|
|
|
if self.secure:
|
|
|
|
from OpenSSL.SSL import Error as SSLError
|
|
|
|
else:
|
|
|
|
class SSLError(Exception): pass
|
2009-01-05 18:55:20 +00:00
|
|
|
try:
|
2008-12-19 10:55:28 +00:00
|
|
|
self.server = server_class((interface, port), handler_class, 0)
|
|
|
|
except SSLError, e:
|
2009-01-05 18:55:20 +00:00
|
|
|
Logger().notifyChannel('xml-rpc-ssl', LOG_CRITICAL, "Can not load the certificate and/or the private key files")
|
2008-12-19 10:55:28 +00:00
|
|
|
sys.exit(1)
|
|
|
|
except Exception, e:
|
2009-01-19 20:51:52 +00:00
|
|
|
Logger().notifyChannel('xml-rpc', LOG_CRITICAL, "Error occur when starting the server daemon: %s" % (e,))
|
2008-12-19 10:55:28 +00:00
|
|
|
sys.exit(1)
|
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
|
2008-08-12 14:44:56 +00:00
|
|
|
def attach(self, path, gw):
|
2008-07-22 14:24:36 +00:00
|
|
|
pass
|
|
|
|
|
|
|
|
def stop(self):
|
|
|
|
self.running = False
|
2008-08-12 14:44:56 +00:00
|
|
|
if os.name != 'nt':
|
2008-12-18 23:54:33 +00:00
|
|
|
self.server.socket.shutdown( hasattr(socket, 'SHUT_RDWR') and socket.SHUT_RDWR or 2 )
|
2008-07-22 14:24:36 +00:00
|
|
|
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
|
2006-12-07 13:41:40 +00:00
|
|
|
|
2007-01-25 12:30:41 +00:00
|
|
|
import tiny_socket
|
2009-01-05 18:55:20 +00:00
|
|
|
class TinySocketClientThread(threading.Thread, OpenERPDispatcher):
|
2008-07-22 14:24:36 +00:00
|
|
|
def __init__(self, sock, threads):
|
|
|
|
threading.Thread.__init__(self)
|
|
|
|
self.sock = sock
|
|
|
|
self.threads = threads
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
import select
|
|
|
|
self.running = True
|
|
|
|
try:
|
|
|
|
ts = tiny_socket.mysocket(self.sock)
|
|
|
|
except:
|
|
|
|
self.sock.close()
|
|
|
|
self.threads.remove(self)
|
|
|
|
return False
|
|
|
|
while self.running:
|
|
|
|
try:
|
|
|
|
msg = ts.myreceive()
|
|
|
|
except:
|
|
|
|
self.sock.close()
|
|
|
|
self.threads.remove(self)
|
|
|
|
return False
|
|
|
|
try:
|
2009-01-05 18:55:20 +00:00
|
|
|
result = self.dispatch(msg[0], msg[1], msg[2:])
|
|
|
|
ts.mysend(result)
|
|
|
|
except OpenERPDispatcherException, e:
|
2009-01-07 18:44:27 +00:00
|
|
|
new_e = Exception(tools.exception_to_unicode(e.exception)) # avoid problems of pickeling
|
2009-01-05 18:55:20 +00:00
|
|
|
ts.mysend(new_e, exception=True, traceback=e.traceback)
|
|
|
|
|
2008-07-22 14:24:36 +00:00
|
|
|
self.sock.close()
|
|
|
|
self.threads.remove(self)
|
|
|
|
return True
|
|
|
|
|
|
|
|
def stop(self):
|
|
|
|
self.running = False
|
2007-01-25 12:30:41 +00:00
|
|
|
|
2008-08-12 14:44:56 +00:00
|
|
|
|
2007-01-25 12:30:41 +00:00
|
|
|
class TinySocketServerThread(threading.Thread):
|
2008-07-22 14:24:36 +00:00
|
|
|
def __init__(self, interface, port, secure=False):
|
|
|
|
threading.Thread.__init__(self)
|
2008-08-12 14:44:56 +00:00
|
|
|
self.__port = port
|
|
|
|
self.__interface = interface
|
2008-07-22 14:24:36 +00:00
|
|
|
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
|
|
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
|
|
self.socket.bind((self.__interface, self.__port))
|
|
|
|
self.socket.listen(5)
|
|
|
|
self.threads = []
|
|
|
|
|
|
|
|
def run(self):
|
|
|
|
import select
|
|
|
|
try:
|
|
|
|
self.running = True
|
|
|
|
while self.running:
|
|
|
|
(clientsocket, address) = self.socket.accept()
|
|
|
|
ct = TinySocketClientThread(clientsocket, self.threads)
|
|
|
|
self.threads.append(ct)
|
|
|
|
ct.start()
|
|
|
|
self.socket.close()
|
|
|
|
except Exception, e:
|
|
|
|
self.socket.close()
|
|
|
|
return False
|
|
|
|
|
|
|
|
def stop(self):
|
2008-08-12 14:44:56 +00:00
|
|
|
self.running = False
|
2008-07-22 14:24:36 +00:00
|
|
|
for t in self.threads:
|
|
|
|
t.stop()
|
|
|
|
try:
|
|
|
|
if hasattr(socket, 'SHUT_RDWR'):
|
|
|
|
self.socket.shutdown(socket.SHUT_RDWR)
|
|
|
|
else:
|
|
|
|
self.socket.shutdown(2)
|
|
|
|
self.socket.close()
|
|
|
|
except:
|
|
|
|
return False
|
2007-01-25 12:30:41 +00:00
|
|
|
|
2008-07-23 15:01:27 +00:00
|
|
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|