changes
This commit is contained in:
@ -3,7 +3,7 @@
|
|||||||
SHAREDSECRET="test123"
|
SHAREDSECRET="test123"
|
||||||
DYNID="testhost"
|
DYNID="testhost"
|
||||||
DATE=`date +%s`
|
DATE=`date +%s`
|
||||||
CHECKSUM=`echo "$DYNID $SHAREDSECRET $DATE" | md5sum | awk '{print $1}'`
|
CHECKSUM=`echo -n "$DYNID $SHAREDSECRET $DATE" | md5sum | awk '{print $1}'`
|
||||||
OUT="$DYNID $DATE $CHECKSUM"
|
OUT="$DYNID $DATE $CHECKSUM"
|
||||||
echo $OUT | nc -q 0 -u 88.198.170.2 9090
|
echo -n $OUT | nc -q 0 -u 127.0.0.1 9090
|
||||||
|
|
||||||
|
193
server/yadyn
Normal file → Executable file
193
server/yadyn
Normal file → Executable file
@ -1,111 +1,130 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
|
|
||||||
import select
|
|
||||||
import socket
|
import socket
|
||||||
|
import Queue
|
||||||
|
import threading
|
||||||
|
import md5
|
||||||
import time
|
import time
|
||||||
import random
|
|
||||||
|
class Entry(object):
|
||||||
|
def __init__(self, dynid, sharedSecret, name):
|
||||||
|
self.dynid = dynid
|
||||||
|
self.sharedSecret = sharedSecret
|
||||||
|
self.name = name
|
||||||
|
self.lastEventTime = 0
|
||||||
|
self.address = ''
|
||||||
|
|
||||||
|
class IllegalEventException(Exception):
|
||||||
|
def __init__(self, msg):
|
||||||
|
self.msg = msg
|
||||||
|
|
||||||
|
|
||||||
ALPHANUM = (0,1,2,3,4,5,6,7,8,9,
|
class Event(object):
|
||||||
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z')
|
def __init__(self, address, data, receiveTime):
|
||||||
|
|
||||||
class DoneException(Exception): pass
|
|
||||||
|
|
||||||
class TimeoutException(Exception): pass
|
|
||||||
|
|
||||||
class Client(object):
|
|
||||||
def __init__(self, sock, address):
|
|
||||||
self.sock = sock
|
|
||||||
self.address = address
|
self.address = address
|
||||||
self.timestamp = int(time.time())
|
self.data = data
|
||||||
self.timeout = 5
|
self.receiveTime = receiveTime
|
||||||
self.state = 0
|
|
||||||
|
def prepare(self):
|
||||||
|
self.port = self.address[1]
|
||||||
|
self.address = self.address[0]
|
||||||
|
(self.dynid, self.msgTime, self.checksum) = self.data.split(' ')
|
||||||
|
self.msgTime = int(self.msgTime)
|
||||||
|
self.prepared = True
|
||||||
|
|
||||||
def process(self):
|
def process(self):
|
||||||
self.timestamp = int(time.time())
|
if not self.prepared:
|
||||||
data = self.sock.recv(8192)
|
self.prepare()
|
||||||
if data == None or data == '':
|
|
||||||
raise DoneException
|
if not ENTRIES.has_key(self.dynid):
|
||||||
if data[-1] in ('\r','\n'):
|
raise IllegalEventException("unknown dynid in event %s" % str(self))
|
||||||
data = data[:-1]
|
entry = ENTRIES[self.dynid]
|
||||||
if data[-1] in ('\r','\n'):
|
|
||||||
data = data[:-1]
|
if self.msgTime + MSG_TIME_CORRIDOR < self.receiveTime:
|
||||||
print "<%s> %d" % (data, len(data))
|
raise IllegalEventException("event too old %s" % str(self))
|
||||||
|
if self.msgTime - MSG_TIME_CORRIDOR > self.receiveTime:
|
||||||
|
raise IllegalEventException("event too young %s" % str(self))
|
||||||
|
|
||||||
|
|
||||||
if self.state == 0:
|
if entry.lastEventTime >= self.msgTime:
|
||||||
#print "State 0"
|
raise IllegalEventException("timing sequence failure in event, possibly replay %s" % str(self))
|
||||||
if data == "hello":
|
|
||||||
self.challenge = ''.join(random.sample(ALPHANUM, 5))
|
di = "%s %s %d" % (self.dynid, entry.sharedSecret, self.msgTime)
|
||||||
print self.challenge
|
d = md5.new(di).hexdigest()
|
||||||
self.sock.send(self.challenge)
|
print "%s, received: %s, calculated: %s" % (di, self.checksum, d)
|
||||||
self.state = 1
|
if d != self.checksum:
|
||||||
return
|
raise IllegalEventException("wrong checksum for event %s" % str(self))
|
||||||
|
|
||||||
|
entry.lastEventTime = self.msgTime
|
||||||
|
|
||||||
|
if entry.address == self.address:
|
||||||
|
print "Same address, nothing to do."
|
||||||
else:
|
else:
|
||||||
raise DoneException
|
entry.address = self.address
|
||||||
elif self.state == 1:
|
print "Set in DNS: %s -> %s" % (entry.name, entry.address)
|
||||||
print "State 1"
|
|
||||||
if data == self.challenge:
|
|
||||||
self.sock.send("OK")
|
|
||||||
raise DoneException
|
|
||||||
|
|
||||||
print "After state machine"
|
|
||||||
|
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if not self.prepared:
|
||||||
|
self.prepare()
|
||||||
|
return "%s from %s:%d" % (self.data, self.address, self.port)
|
||||||
|
|
||||||
|
class Handler(threading.Thread):
|
||||||
|
def __init__(self, queue):
|
||||||
|
threading.Thread.__init__(self)
|
||||||
|
self.q = queue
|
||||||
|
self.setDaemon(True)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
while True:
|
||||||
|
event = self.q.get()
|
||||||
|
try:
|
||||||
|
event.prepare()
|
||||||
|
print "Processing event %s" % str(event)
|
||||||
|
event.process()
|
||||||
|
except IllegalEventException, e:
|
||||||
|
print "Some failure: %s" % e.msg
|
||||||
|
|
||||||
|
class Expirer(threading.Thread):
|
||||||
|
def __init__(self):
|
||||||
|
threading.Thread.__init__(self)
|
||||||
|
self.setDaemon(True)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
while True:
|
||||||
|
print "Expiring ..."
|
||||||
|
currentTime = int(time.time())
|
||||||
|
for entry in ENTRIES.values():
|
||||||
|
if entry.lastEventTime != 0 and entry.lastEventTime + EVENT_LIFE_TIME < currentTime:
|
||||||
|
print "Entry %s expired" % entry.dynid
|
||||||
|
entry.lastEventTime = 0
|
||||||
|
entry.address = NULL_ADDRESS
|
||||||
|
print "Set in DNS: %s -> %s" % (entry.name, entry.address)
|
||||||
|
time.sleep(10)
|
||||||
|
|
||||||
|
|
||||||
def checkTimeout(self):
|
ENTRIES = {
|
||||||
if self.timestamp + self.timeout < int(time.time()):
|
'testhost': Entry('testhost,', 'test123', 'test.test.de'),
|
||||||
raise TimeoutException()
|
}
|
||||||
|
MSG_TIME_CORRIDOR = 5
|
||||||
|
EVENT_LIFE_TIME = 10
|
||||||
|
NULL_ADDRESS = '0.0.0.0'
|
||||||
|
|
||||||
def close(self):
|
q = Queue.Queue()
|
||||||
self.sock.close()
|
|
||||||
|
|
||||||
|
handler = Handler(q)
|
||||||
|
handler.start()
|
||||||
|
|
||||||
|
expirer = Expirer()
|
||||||
|
expirer.start()
|
||||||
|
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
sSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
s.bind(("", 9090))
|
||||||
sSock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
||||||
sSock.bind(("", 9090))
|
|
||||||
sSock.listen(5)
|
|
||||||
print "sSock: ", sSock.fileno()
|
|
||||||
|
|
||||||
p = select.poll()
|
|
||||||
p.register(sSock.fileno(), select.POLLIN)
|
|
||||||
|
|
||||||
clients = {}
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
events = p.poll(1000)
|
data, address = s.recvfrom(256)
|
||||||
|
|
||||||
for (fd, event) in events:
|
|
||||||
# print "fd: %d, event: %d" % (fd, event)
|
|
||||||
|
|
||||||
if fd == sSock.fileno() and (event & select.POLLIN):
|
|
||||||
# print "received connect"
|
|
||||||
cSock, cAddress = sSock.accept()
|
|
||||||
clients[cSock.fileno()] = Client(cSock, cAddress)
|
|
||||||
# print "cSock: %d, address: %s" % (cSock.fileno(), str(cAddress))
|
|
||||||
p.register(cSock.fileno(), select.POLLIN)
|
|
||||||
else:
|
|
||||||
# print "received data for ", fd
|
|
||||||
if event & select.POLLIN:
|
|
||||||
client = clients[fd]
|
|
||||||
try:
|
try:
|
||||||
client.process()
|
q.put_nowait(Event(address, data, int(time.time())))
|
||||||
except Exception, e:
|
except Queue.Full:
|
||||||
print "Closing %d, %s" % (fd, str(e))
|
print "Event %s from %s dropped" % (data, str(address))
|
||||||
client.close()
|
|
||||||
del clients[fd]
|
|
||||||
p.unregister(fd)
|
|
||||||
|
|
||||||
# print "clients: " + str(clients)
|
|
||||||
for fd in clients.keys():
|
|
||||||
try:
|
|
||||||
clients[fd].checkTimeout()
|
|
||||||
except TimeoutException:
|
|
||||||
# print "Timeout %d" % fd
|
|
||||||
clients[fd].close()
|
|
||||||
del clients[fd]
|
|
||||||
p.unregister(fd)
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user