Files
tryton/trytond/protocols/netrpc.py
T

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