134 lines
4.3 KiB
Python
134 lines
4.3 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.
|
|
from trytond.pysocket import PySocket
|
|
from trytond.protocols.sslsocket import SSLSocket
|
|
from trytond.config import CONFIG
|
|
from trytond.protocols.dispatcher import dispatch
|
|
import threading
|
|
import select
|
|
import traceback
|
|
import socket
|
|
import sys
|
|
|
|
|
|
class NetRPCClientThread(threading.Thread):
|
|
def __init__(self, sock, threads, secure):
|
|
threading.Thread.__init__(self)
|
|
self.sock = sock
|
|
self.threads = threads
|
|
self.running = False
|
|
self.secure = secure
|
|
|
|
def run(self):
|
|
self.running = True
|
|
try:
|
|
pysocket = PySocket(self.sock)
|
|
except:
|
|
self.sock.close()
|
|
self.threads.remove(self)
|
|
return False
|
|
timeout = 0
|
|
while self.running:
|
|
(rlist, _, _) = select.select([self.sock], [], [], 1)
|
|
if not rlist:
|
|
timeout += 1
|
|
if timeout > 600:
|
|
break
|
|
continue
|
|
timeout = 0
|
|
try:
|
|
msg = pysocket.receive()
|
|
except:
|
|
pysocket.disconnect()
|
|
self.threads.remove(self)
|
|
return False
|
|
host, port = self.sock.getpeername()[:2]
|
|
try:
|
|
res = dispatch(host, port, 'NetRPC', *msg)
|
|
pysocket.send(res)
|
|
except Exception, exception:
|
|
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
|
|
tback = sys.exc_info()[2]
|
|
pdb.post_mortem(tback)
|
|
try:
|
|
pysocket.send(exception.args, exception=True,
|
|
traceback=tb_s)
|
|
except:
|
|
pysocket.disconnect()
|
|
self.threads.remove(self)
|
|
return False
|
|
pysocket.disconnect()
|
|
self.threads.remove(self)
|
|
return True
|
|
|
|
def stop(self):
|
|
self.running = False
|
|
|
|
|
|
class NetRPCServerThread(threading.Thread):
|
|
def __init__(self, interface, port, secure=False):
|
|
threading.Thread.__init__(self)
|
|
self.socket = None
|
|
if socket.has_ipv6:
|
|
try:
|
|
socket.getaddrinfo(interface or None, port, socket.AF_INET6)
|
|
self.socket = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
|
|
except:
|
|
pass
|
|
if self.socket is None:
|
|
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
if secure:
|
|
self.socket = SSLSocket(self.socket)
|
|
self.socket.bind((interface, port))
|
|
self.socket.listen(5)
|
|
self.threads = []
|
|
self.secure = secure
|
|
self.running = False
|
|
|
|
def run(self):
|
|
try:
|
|
self.running = True
|
|
while self.running:
|
|
if not int(CONFIG['max_thread']) \
|
|
or len(self.threads) < int(CONFIG['max_thread']):
|
|
(clientsocket, _) = self.socket.accept()
|
|
c_thread = NetRPCClientThread(clientsocket, self.threads,
|
|
self.secure)
|
|
self.threads.append(c_thread)
|
|
c_thread.start()
|
|
except:
|
|
try:
|
|
self.socket.close()
|
|
except:
|
|
pass
|
|
return False
|
|
|
|
def stop(self):
|
|
self.running = False
|
|
while len(self.threads):
|
|
try:
|
|
thread = self.threads[0]
|
|
thread.stop()
|
|
thread.join()
|
|
except:
|
|
pass
|
|
try:
|
|
if hasattr(socket, 'SHUT_RDWR'):
|
|
self.socket.shutdown(socket.SHUT_RDWR)
|
|
else:
|
|
self.socket.shutdown(2)
|
|
self.socket.close()
|
|
except:
|
|
return False
|