changes
This commit is contained in:
@ -3,7 +3,7 @@
|
||||
SHAREDSECRET="test123"
|
||||
DYNID="testhost"
|
||||
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"
|
||||
echo $OUT | nc -q 0 -u 88.198.170.2 9090
|
||||
echo -n $OUT | nc -q 0 -u 127.0.0.1 9090
|
||||
|
||||
|
195
server/yadyn
Normal file → Executable file
195
server/yadyn
Normal file → Executable file
@ -1,111 +1,130 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import select
|
||||
import socket
|
||||
import Queue
|
||||
import threading
|
||||
import md5
|
||||
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,
|
||||
'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')
|
||||
|
||||
class DoneException(Exception): pass
|
||||
|
||||
class TimeoutException(Exception): pass
|
||||
|
||||
class Client(object):
|
||||
def __init__(self, sock, address):
|
||||
self.sock = sock
|
||||
class Event(object):
|
||||
def __init__(self, address, data, receiveTime):
|
||||
self.address = address
|
||||
self.timestamp = int(time.time())
|
||||
self.timeout = 5
|
||||
self.state = 0
|
||||
self.data = data
|
||||
self.receiveTime = receiveTime
|
||||
|
||||
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):
|
||||
self.timestamp = int(time.time())
|
||||
data = self.sock.recv(8192)
|
||||
if data == None or data == '':
|
||||
raise DoneException
|
||||
if data[-1] in ('\r','\n'):
|
||||
data = data[:-1]
|
||||
if data[-1] in ('\r','\n'):
|
||||
data = data[:-1]
|
||||
print "<%s> %d" % (data, len(data))
|
||||
if not self.prepared:
|
||||
self.prepare()
|
||||
|
||||
if not ENTRIES.has_key(self.dynid):
|
||||
raise IllegalEventException("unknown dynid in event %s" % str(self))
|
||||
entry = ENTRIES[self.dynid]
|
||||
|
||||
if self.msgTime + MSG_TIME_CORRIDOR < self.receiveTime:
|
||||
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:
|
||||
#print "State 0"
|
||||
if data == "hello":
|
||||
self.challenge = ''.join(random.sample(ALPHANUM, 5))
|
||||
print self.challenge
|
||||
self.sock.send(self.challenge)
|
||||
self.state = 1
|
||||
return
|
||||
else:
|
||||
raise DoneException
|
||||
elif self.state == 1:
|
||||
print "State 1"
|
||||
if data == self.challenge:
|
||||
self.sock.send("OK")
|
||||
raise DoneException
|
||||
if entry.lastEventTime >= self.msgTime:
|
||||
raise IllegalEventException("timing sequence failure in event, possibly replay %s" % str(self))
|
||||
|
||||
print "After state machine"
|
||||
di = "%s %s %d" % (self.dynid, entry.sharedSecret, self.msgTime)
|
||||
d = md5.new(di).hexdigest()
|
||||
print "%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
|
||||
|
||||
if entry.address == self.address:
|
||||
print "Same address, nothing to do."
|
||||
else:
|
||||
entry.address = self.address
|
||||
print "Set in DNS: %s -> %s" % (entry.name, entry.address)
|
||||
|
||||
|
||||
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):
|
||||
if self.timestamp + self.timeout < int(time.time()):
|
||||
raise TimeoutException()
|
||||
ENTRIES = {
|
||||
'testhost': Entry('testhost,', 'test123', 'test.test.de'),
|
||||
}
|
||||
MSG_TIME_CORRIDOR = 5
|
||||
EVENT_LIFE_TIME = 10
|
||||
NULL_ADDRESS = '0.0.0.0'
|
||||
|
||||
def close(self):
|
||||
self.sock.close()
|
||||
q = Queue.Queue()
|
||||
|
||||
handler = Handler(q)
|
||||
handler.start()
|
||||
|
||||
expirer = Expirer()
|
||||
expirer.start()
|
||||
|
||||
|
||||
sSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
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 = {}
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.bind(("", 9090))
|
||||
|
||||
while True:
|
||||
events = p.poll(1000)
|
||||
|
||||
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:
|
||||
client.process()
|
||||
except Exception, e:
|
||||
print "Closing %d, %s" % (fd, str(e))
|
||||
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)
|
||||
data, address = s.recvfrom(256)
|
||||
try:
|
||||
q.put_nowait(Event(address, data, int(time.time())))
|
||||
except Queue.Full:
|
||||
print "Event %s from %s dropped" % (data, str(address))
|
||||
|
||||
|
Reference in New Issue
Block a user