mirror of https://github.com/dirtbags/moth.git
Convert flagd to use medusa
This commit is contained in:
parent
efe3f5c5b9
commit
c2d685005b
170
flagd.py
170
flagd.py
|
@ -1,8 +1,9 @@
|
||||||
#! /usr/bin/env python3
|
#! /usr/bin/env python3
|
||||||
|
|
||||||
import socketserver
|
import asyncore
|
||||||
import threading
|
import asynchat
|
||||||
import queue
|
import socket
|
||||||
|
import functools
|
||||||
import time
|
import time
|
||||||
import hmac
|
import hmac
|
||||||
import optparse
|
import optparse
|
||||||
|
@ -14,63 +15,129 @@ key = b'My First Shared Secret (tm)'
|
||||||
def hexdigest(data):
|
def hexdigest(data):
|
||||||
return hmac.new(key, data).hexdigest()
|
return hmac.new(key, data).hexdigest()
|
||||||
|
|
||||||
house = 'dirtbags' # House team name
|
class Submitter(asyncore.dispatcher):
|
||||||
flags = {}
|
def __init__(self, host='localhost', port=6667):
|
||||||
toscore = queue.Queue(50)
|
asyncore.dispatcher.__init__(self)
|
||||||
|
self.create_socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
self.connect((host, port))
|
||||||
|
self.pending = []
|
||||||
|
self.unacked = {}
|
||||||
|
self.flags = {}
|
||||||
|
self.lastupdate = 0
|
||||||
|
self.lastretrans = 0
|
||||||
|
self.id = 0
|
||||||
|
|
||||||
class Submitter(threading.Thread):
|
def submit(self, now, cat, team, score):
|
||||||
def run(self):
|
q = points.encode_request(self.id, now, cat, team, score)
|
||||||
self.sock = pointscli.makesock('localhost')
|
self.id += 1
|
||||||
while True:
|
self.pending.append(q)
|
||||||
|
self.unacked[id] = q
|
||||||
|
|
||||||
|
def writable(self):
|
||||||
|
print('writable?')
|
||||||
|
now = int(time.time())
|
||||||
|
if now >= self.lastupdate + 60:
|
||||||
|
for cat, team in self.flags.items():
|
||||||
|
self.submit(now, cat, team, 1)
|
||||||
|
self.lastupdate = now
|
||||||
|
if now > self.lastretrans:
|
||||||
|
for id, q in self.unacked.items():
|
||||||
|
self.pending.append(q)
|
||||||
|
self.lastretrans = now
|
||||||
|
ret = bool(self.pending)
|
||||||
|
print(ret)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def handle_write(self):
|
||||||
|
dgram = self.pending.pop(0)
|
||||||
|
self.socket.send(dgram)
|
||||||
|
|
||||||
|
def handle_read(self):
|
||||||
|
dgram, peer = self.socket.recvfrom(4096)
|
||||||
try:
|
try:
|
||||||
delay = 60 - (time.time() % 60)
|
id, txt = points.decode_response(dgram)
|
||||||
cat, team = toscore.get(True, delay)
|
except ValueError:
|
||||||
self.submit(cat, team)
|
# Ignore invalid packets
|
||||||
except queue.Empty:
|
return
|
||||||
self.once()
|
|
||||||
|
|
||||||
def once(self):
|
|
||||||
global flags
|
|
||||||
global toscore
|
|
||||||
|
|
||||||
for cat, team in flags.items():
|
|
||||||
self.submit(cat, team)
|
|
||||||
|
|
||||||
def submit(self, cat, team):
|
|
||||||
try:
|
try:
|
||||||
pointscli.submit(self.sock, cat, team, 1)
|
del self.unacked[id]
|
||||||
except:
|
except KeyError:
|
||||||
traceback.print_exc()
|
pass
|
||||||
|
if txt != 'OK':
|
||||||
|
raise ValueError(txt)
|
||||||
|
|
||||||
|
def set_flag(self, cat, team):
|
||||||
|
now = int(time.time())
|
||||||
|
|
||||||
|
team = team or points.house
|
||||||
|
|
||||||
|
self.flags[cat] = team
|
||||||
|
self.submit(now, cat, team, 1)
|
||||||
|
|
||||||
|
|
||||||
class CategoryHandler(socketserver.StreamRequestHandler):
|
class Listener(asyncore.dispatcher):
|
||||||
def handle(self):
|
def __init__(self, connection_factory, host='localhost', port=6668):
|
||||||
global flags
|
asyncore.dispatcher.__init__(self)
|
||||||
|
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
self.set_reuse_addr()
|
||||||
|
self.bind((host, port))
|
||||||
|
self.listen(4)
|
||||||
|
self.connection_factory = connection_factory
|
||||||
|
|
||||||
|
def handle_accept(self):
|
||||||
|
conn, addr = self.accept()
|
||||||
|
self.connection_factory(conn)
|
||||||
|
|
||||||
|
|
||||||
|
class FlagServer(asynchat.async_chat):
|
||||||
|
def __init__(self, submitter, sock):
|
||||||
|
asynchat.async_chat.__init__(self, sock=sock)
|
||||||
|
self.set_terminator(b'\n')
|
||||||
|
self.submitter = submitter
|
||||||
|
self.flag = None
|
||||||
|
self.inbuf = []
|
||||||
|
self.cat = None
|
||||||
|
|
||||||
|
def err(self, txt):
|
||||||
|
e = ('ERROR: Closing Link: %s\n' % txt)
|
||||||
|
self.push(e.encode('utf-8'))
|
||||||
|
self.close()
|
||||||
|
|
||||||
|
def collect_incoming_data(self, data):
|
||||||
|
if len(self.inbuf) > 10:
|
||||||
|
return self.err('max sendq exceeded')
|
||||||
|
self.inbuf.append(data)
|
||||||
|
|
||||||
|
def set_flag(self, team):
|
||||||
|
self.flag = team
|
||||||
|
if self.cat:
|
||||||
|
self.submitter.set_flag(self.cat, team)
|
||||||
|
|
||||||
|
def found_terminator(self):
|
||||||
|
data = b''.join(self.inbuf)
|
||||||
|
self.inbuf = []
|
||||||
|
if not self.cat:
|
||||||
try:
|
try:
|
||||||
catpass = self.rfile.readline().strip()
|
cat, passwd = data.split(b':::')
|
||||||
cat, passwd = catpass.split(b':::')
|
|
||||||
passwd = passwd.decode('utf-8')
|
passwd = passwd.decode('utf-8')
|
||||||
if passwd != hexdigest(cat):
|
if passwd != hexdigest(cat):
|
||||||
self.wfile.write(b'ERROR :Closing Link: Invalid password\n')
|
return self.err('Invalid password')
|
||||||
return
|
self.cat = cat.decode('utf-8')
|
||||||
cat = cat.decode('utf-8')
|
except ValueError:
|
||||||
except ValueError as foo:
|
return self.err('Invalid command')
|
||||||
self.wfile.write(b'ERROR :Closing Link: Invalid command\n')
|
self.set_flag(None)
|
||||||
return
|
else:
|
||||||
|
team = data.strip().decode('utf-8')
|
||||||
|
self.set_flag(team)
|
||||||
|
|
||||||
flags[cat] = house
|
def handle_close(self):
|
||||||
while True:
|
self.set_flag(None)
|
||||||
team = self.rfile.readline().strip().decode('utf-8')
|
|
||||||
if not team:
|
|
||||||
break
|
|
||||||
flags[cat] = team
|
|
||||||
toscore.put((cat, team)) # score a point immediately
|
|
||||||
flags[cat] = house
|
|
||||||
|
|
||||||
class MyServer(socketserver.ThreadingTCPServer):
|
|
||||||
allow_reuse_address = True
|
|
||||||
|
|
||||||
|
def start():
|
||||||
|
submitter = Submitter()
|
||||||
|
server = Listener(functools.partial(FlagServer, submitter))
|
||||||
|
return (submitter, server)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
p = optparse.OptionParser()
|
p = optparse.OptionParser()
|
||||||
|
@ -81,11 +148,8 @@ def main():
|
||||||
print('%s:::%s' % (opts.cat, hexdigest(opts.cat.encode('utf-8'))))
|
print('%s:::%s' % (opts.cat, hexdigest(opts.cat.encode('utf-8'))))
|
||||||
return
|
return
|
||||||
|
|
||||||
submitter = Submitter()
|
start()
|
||||||
submitter.start()
|
asyncore.loop()
|
||||||
server = MyServer(('', 6668), CategoryHandler)
|
|
||||||
server.serve_forever()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
#! /usr/bin/env python3
|
||||||
|
|
||||||
|
import asyncore
|
||||||
|
import pointsd
|
||||||
|
import flagd
|
||||||
|
|
||||||
|
def main():
|
||||||
|
pointsd.start()
|
||||||
|
flagd.start()
|
||||||
|
asyncore.loop(timeout=30, use_poll=True)
|
||||||
|
|
||||||
|
main()
|
Loading…
Reference in New Issue