import SocketServer import time from Logging import * class NetStringError(ValueError): pass def NetStringDecode(s): try: length, data = s.split(':') except ValueError: raise NetStringError, "Separator not found" try: length = int(length) except ValueError: raise NetStringError, "Can not read length" if len(data) != length+1: raise NetStringError, "Data has unexpected length" if data[-1] != ',': raise NetStringError, "End-delimiter not found" return data[:-1] def NetStringEncode(s): return str(len(s)) + ":" + s + "," class MyPermanentVerifierException(ValueError): pass class MyTemporaryVerifierException(ValueError): pass class MyBaseRequestHandler(SocketServer.BaseRequestHandler): def handle(self): debug("Connected from " + str(self.client_address)) self.localSetup() while 1: receivedData = self.request.recv(8192) if (receivedData == None) or (len(receivedData) == 0): break debug("Data: (%s)" % receivedData) self.request.sendall(self.process(receivedData)) self.request.close(); self.localFinish() debug("Disconnected") def process(self, data): debug("MyBaseRequestHandler.process") return data def localSetup(self): pass def localfinish(self): pass class SendmailAdaptor: PERM = "PERM " OK = "OK " NOTFOUND = "NOTFOUND " TEMP = "TEMP " def preProcess(self, data): try: data = NetStringDecode(data) klass, data = data.split(' ') return klass, data except NetStringError, arg: raise MyPermanentVerifierException, arg except ValueError: raise MyPermanentVerifierException, " expected, only one found" def postProcess(self, data): return NetStringEncode(data) def process(self, data): startTime = time.time() try: klass, data2 = self.preProcess(data) arg = self.execute(klass, data2) code = SendmailAdaptor.OK except MyPermanentVerifierException, arg: code, arg = SendmailAdaptor.PERM, str(arg) except MyTemporaryVerifierException, arg: code, arg = SendmailAdaptor.TEMP, str(arg) endTime = time.time() log("Class: %s, Data: %s, Code: %s, Arg: %s, Delay: %f" % (klass, data2, code, arg, endTime-startTime)) return self.postProcess(code + arg) def execute(self, data): return data class NullAdaptor(SendmailAdaptor): def preProcess(self, data): return re.compile(r'^(.*?)[\r\n]{1,2}$').match(data).group(1) def postProcess(self, data): return data + "\n" class SendmailDispatcher(SendmailAdaptor, MyBaseRequestHandler): pluginContainerObjects = {} def registerAll(config): for section in config.get('Daemon', 'Plugins').split(','): SendmailDispatcher.register(section, config) registerAll = staticmethod(registerAll) def register(section, config): cfg = Config(section, config) className = cfg.get('ContainerClass') moduleName = cfg.get('ContainerModule') if className == None: className = 'smmapBaseHandlerContainer' else: if moduleName == None: moduleName == className m = __import__(moduleName) log("Registering %s, %s" % (section, className)) klass = eval("m.%s" % className) containerObject = klass(cfg) containerObject.setup() SendmailDispatcher.pluginContainerObjects[section] = containerObject register = staticmethod(register) def localSetup(self): self.pluginWorkerObjects = {} def localFinish(self): for o in self.pluginWorkerObjects.values(): o.finish() def execute(self, klass, data): if not self.pluginContainerObjects.has_key(klass): raise MyPermanentVerifierException, "Class %s not implemented" % klass elif not self.pluginWorkerObjects.has_key(klass): debug("Instantiate worker %s" % klass) self.pluginWorkerObjects[klass] = self.pluginContainerObjects[klass].getWorker() return self.pluginWorkerObjects[klass].execute(data) class Config(object): def __init__(self, section, config): self.section = section self.config = config def getSection(self): return self.section def get(self, item): return self.config.get(self.section, item) class smmapBaseHandlerWorker(object): def __init__(self, container): self.container = container def setup(self): pass def finish(self): pass def execute(self, data): raise NotImplementedError class smmapBaseHandlerContainer(object): def __init__(self, cfg): self.config = cfg workerClassName = cfg.get('WorkerClass') workerModuleName = cfg.get('WorkerModule') if workerModuleName == None: workerModuleName = workerClassName m = __import__(workerModuleName) self.workerClass = eval("m.%s" % workerClassName) def setup(self): pass def finish(self): pass def getWorker(self): worker = self.workerClass(self) worker.setup() return worker