6 import SimpleXMLRPCServer,signal,sys,xmlrpclib
23 class ServiceEndPointCall(object):
24 def __init__(self,id,method):
27 def __call__(self,*args):
28 _res[self._id]=self._meth(*args)
31 class ServiceEndPoint(object):
32 def __init__(self, name, id):
38 self._meth[m]=s._method[m]
39 def __getattr__(self, name):
40 return ServiceEndPointCall(self._id, self._meth[name])
42 class Service(object):
43 _serviceEndPointID = 0
44 def __init__(self, name, audience=''):
48 self.exportedMethods=None
49 self._response_process=None
50 self._response_process_id=None
53 def joinGroup(self,name):
54 if not name in _group:
56 _group[name][self.__name]=self
58 def exportMethod(self, m):
60 self._method[m.__name__]=m
62 def serviceEndPoint(self,s):
63 if Service._serviceEndPointID >= 2**16:
64 Service._serviceEndPointID = 0
65 Service._serviceEndPointID += 1
66 return ServiceEndPoint(s, self._serviceEndPointID)
68 def conversationId(self):
71 def processResponse(self,s,id):
72 self._response_process, self._response_process_id = s, id
74 def processFailure(self,s,id):
77 def resumeResponse(self,s):
80 def cancelResponse(self,s):
83 def suspendResponse(self,s):
84 if self._response_process:
85 self._response_process(self._response_process_id,
86 _res[self._response_process_id])
87 self._response_process=None
88 self._response=s(self._response_process_id)
90 def abortResponse(self,error, description, origin, details):
92 if not tools.config['debug_mode']:
93 raise Exception("%s -- %s\n\n%s"%(origin,description,details))
97 def currentFailure(self,s):
100 class LocalService(Service):
101 def __init__(self, name):
106 setattr(self,m,s._method[m])
108 class ServiceUnavailable(Exception):
115 LOG_CRITICAL='critical'
118 from tools import config
121 if config['logfile']:
122 logf = config['logfile']
123 # test if the directories exist, else create them
125 if not os.path.exists(os.path.dirname(logf)):
126 os.makedirs(os.path.dirname(logf))
129 handler = logging.StreamHandler(fd)
131 sys.stderr.write("ERROR: couldn't open the logfile\n")
132 handler = logging.StreamHandler(sys.stdout)
134 sys.stderr.write("ERROR: couldn't create the logfile directory\n")
135 handler = logging.StreamHandler(sys.stdout)
137 handler = logging.StreamHandler(sys.stdout)
139 # create a format for log messages and dates
140 formatter = logging.Formatter('%(asctime)s %(levelname)s:%(name)s:%(message)s', '%a, %d %b %Y %H:%M:%S')
142 # tell the handler to use this format
143 handler.setFormatter(formatter)
145 # add the handler to the root logger
146 logging.getLogger().addHandler(handler)
147 logging.getLogger().setLevel(logging.INFO)
150 class Logger(object):
151 def notifyChannel(self,name,level,msg):
152 log = logging.getLogger(name)
153 getattr(log,level)(msg)
159 def setAlarm(self, fn, dt, args=[], kwargs={}):
160 wait = dt - time.time()
162 self._logger.notifyChannel(
164 "Job scheduled in %s seconds for %s.%s" % (wait,
165 fn.im_class.__name__,
167 timer = threading.Timer(wait, fn, args, kwargs)
169 self._timers.append(timer)
170 for timer in self._timers[:]:
171 if not timer.isAlive():
172 self._timers.remove(timer)
175 for timer in cls._timers:
177 quit=classmethod(quit)
179 class RpcGateway(object):
180 def __init__(self, name):
183 class Dispatcher(object):
186 def monitor(self,signal):
191 class xmlrpc(object):
192 class RpcGateway(object):
193 def __init__(self, name):
196 class GenericXMLRPCRequestHandler:
197 def _dispatch(self, method, params):
200 n=self.path.split("/")[-1]
203 s._service._response=None
205 res=s._service._response
211 logger.notifyChannel("web-services", LOG_ERROR, 'Exception in call: ' + reduce(lambda x, y: x+y, traceback.format_exc()))
214 if tools.config['debug_mode']:
216 tb = sys.exc_info()[2]
218 raise xmlrpclib.Fault(1,s)
220 class SimpleXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SimpleXMLRPCServer.SimpleXMLRPCRequestHandler):
224 class SecureXMLRPCRequestHandler(GenericXMLRPCRequestHandler, SecureXMLRPCServer.SecureXMLRPCRequestHandler):
229 class SimpleThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SimpleXMLRPCServer.SimpleXMLRPCServer):
230 def server_bind(self):
231 self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
232 SimpleXMLRPCServer.SimpleXMLRPCServer.server_bind(self)
235 class SecureThreadedXMLRPCServer(SocketServer.ThreadingMixIn, SecureXMLRPCServer.SecureXMLRPCServer):
236 def server_bind(self):
237 self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
238 SecureXMLRPCServer.SecureXMLRPCServer.server_bind(self)
242 class HttpDaemon(threading.Thread):
243 def __init__(self, interface,port, secure=False):
244 threading.Thread.__init__(self)
246 self.__interface=interface
247 if secure and HAS_SSL:
248 self.server = SecureThreadedXMLRPCServer((interface, port), SecureXMLRPCRequestHandler,0)
250 self.server = SimpleThreadedXMLRPCServer((interface, port), SimpleXMLRPCRequestHandler,0)
252 def attach(self,path,gw):
257 if hasattr(socket, 'SHUT_RDWR'):
258 self.server.socket.shutdown(socket.SHUT_RDWR)
260 self.server.socket.shutdown(2)
261 self.server.socket.close()
264 self.server.register_introspection_functions()
268 self.server.handle_request()
271 # If the server need to be run recursively
273 #signal.signal(signal.SIGALRM, self.my_handler)
276 # self.server.handle_request()
277 #signal.alarm(0) # Disable the alarm
280 class TinySocketClientThread(threading.Thread):
281 def __init__(self, sock, threads):
282 threading.Thread.__init__(self)
284 self.threads = threads
292 ts = tiny_socket.mysocket(self.sock)
297 s=LocalService(msg[0])
299 s._service._response=None
301 res=s._service._response
307 logger.notifyChannel("web-services", LOG_ERROR, 'Exception in call: ' + reduce(lambda x, y: x+y, traceback.format_exc()))
310 if tools.config['debug_mode']:
312 tb = sys.exc_info()[2]
314 ts.mysend(e, exception=True)
316 self.threads.remove(self)
324 class TinySocketServerThread(threading.Thread):
325 def __init__(self, interface, port, secure=False):
326 threading.Thread.__init__(self)
328 self.__interface=interface
329 self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
330 self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
331 self.socket.bind((self.__interface, self.__port))
332 self.socket.listen(5)
340 (clientsocket, address) = self.socket.accept()
341 ct = TinySocketClientThread(clientsocket, self.threads)
343 self.threads.append(ct)
351 for t in self.threads:
354 if hasattr(socket, 'SHUT_RDWR'):
355 self.socket.shutdown(socket.SHUT_RDWR)
357 self.socket.shutdown(2)