1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
|
#!/usr/bin/env python3
import argparse
import asyncio
import logging
import os
import sys
import time
import websockets.server as ws_server
from websockets.exceptions import ConnectionClosedError
log = logging.getLogger(__name__)
logging.basicConfig(
format="[%(asctime)s] %(message)s",
level=logging.DEBUG,
)
async def echo(websocket):
try:
async for message in websocket:
try:
log.info(f'got request {message}')
except Exception as e:
log.error(f'error {e} getting path from {message}')
await websocket.send(message)
except ConnectionClosedError:
pass
async def on_async_conn(conn):
rpath = str(conn.path)
pcomps = rpath[1:].split('/')
if len(pcomps) == 0:
pcomps = ['echo'] # default handler
log.info(f'connection for {pcomps}')
if pcomps[0] == 'echo':
log.info(f'/echo endpoint')
for message in await conn.recv():
await conn.send(message)
elif pcomps[0] == 'text':
await conn.send('hello!')
elif pcomps[0] == 'file':
if len(pcomps) < 2:
conn.close(code=4999, reason='unknown file')
return
fpath = os.path.join('../', pcomps[1])
if not os.path.exists(fpath):
conn.close(code=4999, reason='file not found')
return
bufsize = 0
if len(pcomps) > 2:
bufsize = int(pcomps[2])
if bufsize <= 0:
bufsize = 16*1024
delay_ms = 0
if len(pcomps) > 3:
delay_ms = int(pcomps[3])
n = 1
if len(pcomps) > 4:
n = int(pcomps[4])
for _ in range(n):
with open(fpath, 'r+b') as fd:
while True:
buf = fd.read(bufsize)
if buf is None or len(buf) == 0:
break
await conn.send(buf)
if delay_ms > 0:
time.sleep(delay_ms/1000)
else:
log.info(f'unknown endpoint: {rpath}')
await conn.close(code=4999, reason='path unknown')
await conn.close(code=1000, reason='')
async def run_server(port):
log.info(f'starting server on port {port}')
async with ws_server.serve(ws_handler=on_async_conn,
host="localhost", port=port):
await asyncio.Future()
async def main():
parser = argparse.ArgumentParser(prog='scorecard',
description="Run a websocket echo server.")
parser.add_argument("--port", type=int,
default=0, help="port to listen on")
args = parser.parse_args()
if args.port == 0:
sys.stderr.write('need --port\n')
sys.exit(1)
logging.basicConfig(
format="%(asctime)s %(message)s",
level=logging.DEBUG,
)
await run_server(args.port)
if __name__ == "__main__":
asyncio.run(main())
|