master
Raw Download raw file
  1import asyncio
  2import logging
  3from utils import find_free_port
  4from flag import random_flag_index
  5from aiohttp import web
  6
  7closers = []
  8runners = []
  9
 10
 11async def homepage_handler(request):
 12    return web.HTTPFound("/index.html")
 13
 14
 15async def homepage(port=8001):
 16    app = web.Application()
 17    app.router.add_route("*", "/", homepage_handler)
 18    app.router.add_static(prefix="/", path="/var/www/html/srs/")
 19    runner = web.AppRunner(app)
 20    await runner.setup()
 21    site = web.TCPSite(runner, "127.0.0.1", port)
 22    logging.info(f"{site.name} starting")
 23    await site.start()
 24    runners.append(runner)
 25    return
 26
 27
 28class ClosingHandler:
 29    def __init__(self, exit_event):
 30        self.exit_event = exit_event
 31
 32    def next_port():
 33        return self.next_port
 34
 35    async def default(self, request):
 36        self.exit_event.set()
 37        self.next_port = find_free_port()
 38        data = {
 39            "now": request.url.port,
 40            "next": self.next_port,
 41            "flag-slice": random_flag_index(),
 42        }
 43        return web.json_response(data)
 44
 45
 46# single request server
 47async def srs(loop, port=None):
 48
 49    # create app handler and closing event
 50    closing_time = asyncio.Event()
 51    closing_task = asyncio.create_task(closing_time.wait())
 52    closers.append(closing_time)
 53    handler = ClosingHandler(closing_time)
 54
 55    # add handler to new application runner
 56    app = web.Application()
 57    app.add_routes([web.get("/", handler.default)])
 58    runner = web.AppRunner(app)
 59    await runner.setup()
 60
 61    # start app on a specific tcp port
 62    if port == None:
 63        port = find_free_port()
 64    site = web.TCPSite(runner, "0.0.0.0", port)
 65    logging.info(f"{site.name} starting")
 66    try:
 67        await site.start()
 68    except OSError:
 69        logging.warn(
 70            f"port {port} already in use, trying a different one"
 71        )
 72        await srs(loop)
 73
 74    # wait for closing event
 75    await closing_task
 76    logging.info(f"{site.name} closing")
 77    await runner.cleanup()
 78
 79    loop.create_task(srs(loop, handler.next_port))
 80
 81
 82if __name__ == "__main__":
 83    logging.basicConfig(level=logging.DEBUG)
 84
 85    loop = asyncio.get_event_loop()
 86
 87    loop.create_task(homepage())
 88
 89    for i in range(100):
 90        loop.create_task(srs(loop))
 91
 92    try:
 93        loop.run_forever()
 94    except:
 95        logging.info("\nexiting...")
 96    finally:
 97        for c in closers:
 98            c.set()  # trigger close event which runs runner.cleanup()
 99        for r in runners:
100            loop.create_task(r.cleanup())