191 lines
5.3 KiB
Python
191 lines
5.3 KiB
Python
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, "<class> <data> 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
|
|
|
|
|
|
|
|
|
|
|