import md5 from logger import Logger class IllegalEventException(Exception): def __init__(self, msg): self.msg = msg class Event(object): @classmethod def setParams(cls, entries, msgTimeCorridor, dnsq): cls.entries = entries cls.msgTimeCorridor = msgTimeCorridor cls.dnsq = dnsq def __init__(self, address, data, receiveTime): self.address = address self.data = data self.receiveTime = receiveTime def prepare(self): self.port = self.address[1] self.address = self.address[0] parts = self.data.split(' ') if len(parts) != 3: raise IllegalEventException("data format error 1") (self.dynid, self.msgTime, self.checksum) = self.data.split(' ') try: self.msgTime = int(self.msgTime) except ValueError, e: raise IllegalEventException("data format error 2") self.prepared = True def process(self): if not self.prepared: self.prepare() if not Event.entries.has_key(self.dynid): raise IllegalEventException("unknown dynid in event %s" % str(self)) entry = Event.entries[self.dynid] if self.msgTime + Event.msgTimeCorridor < self.receiveTime: raise IllegalEventException("event too old %s" % str(self)) if self.msgTime - Event.msgTimeCorridor > self.receiveTime: raise IllegalEventException("event too young %s" % str(self)) if entry.lastEventTime >= self.msgTime: raise IllegalEventException("timing sequence failure in event, possibly replay %s" % str(self)) di = "%s %s %d" % (self.dynid, entry.sharedSecret, self.msgTime) d = md5.new(di).hexdigest() Logger.debug("%s, received: %s, calculated: %s" % (di, self.checksum, d)) if d != self.checksum: raise IllegalEventException("wrong checksum for event %s" % str(self)) entry.lastEventTime = self.msgTime entry.address = self.address Logger.debug("Set in DNS: %s -> %s" % (entry.name, entry.address)) try: Event.dnsq.put_nowait(entry) except Queue.Full, e: Logger.log("Dns Queue overrun, drop event for %s" % str(entry)) def __str__(self): if not self.prepared: self.prepare() return "%s from %s:%d" % (self.data, self.address, self.port)