2024-08-27 22:58:17 +00:00
|
|
|
#!/usr/bin/env python3
|
2024-08-27 19:44:15 +00:00
|
|
|
import asyncio
|
|
|
|
import websockets
|
|
|
|
import hashlib
|
2024-08-27 22:00:08 +00:00
|
|
|
import random
|
2024-08-27 22:05:41 +00:00
|
|
|
import os
|
|
|
|
import sys
|
2024-08-27 19:44:15 +00:00
|
|
|
|
2024-08-27 20:26:35 +00:00
|
|
|
|
|
|
|
import conn
|
|
|
|
|
|
|
|
|
2024-08-27 22:05:41 +00:00
|
|
|
LOCALHOST = '::1'
|
|
|
|
DEFAULT_LISTEN_PORT = 6443
|
|
|
|
WEBSOCKET_URL = 'ws://localhost:9999'
|
2024-08-27 19:44:15 +00:00
|
|
|
|
|
|
|
|
2024-08-27 21:21:22 +00:00
|
|
|
async def handle_client(socket_reader, socket_writer):
|
2024-08-27 22:00:08 +00:00
|
|
|
socket_id = random.randint(0, 9000)
|
2024-08-27 19:44:15 +00:00
|
|
|
|
2024-08-27 21:21:22 +00:00
|
|
|
|
2024-08-27 22:00:08 +00:00
|
|
|
async with websockets.connect(WEBSOCKET_URL) as websocket:
|
|
|
|
try:
|
|
|
|
print(f"New client connected socket {socket_id}")
|
2024-08-27 21:21:22 +00:00
|
|
|
m = conn.WSMsg(socket_id, conn.MsgType.CONNECT)
|
2024-08-27 22:58:17 +00:00
|
|
|
print(f'TCP>WS: {m}')
|
2024-08-27 21:21:22 +00:00
|
|
|
await websocket.send(m.to_bytes())
|
|
|
|
|
2024-08-27 19:44:15 +00:00
|
|
|
# Forwarding data from client to WebSocket
|
|
|
|
async def client_to_websocket():
|
|
|
|
while True:
|
2024-08-27 21:21:22 +00:00
|
|
|
data = await socket_reader.read(2024)
|
2024-08-27 19:44:15 +00:00
|
|
|
if not data:
|
2024-08-27 22:00:08 +00:00
|
|
|
c = conn.WSMsg(socket_id, conn.MsgType.DISCONNECT)
|
|
|
|
print(f"Client {socket_id} disconnected")
|
2024-08-27 22:58:17 +00:00
|
|
|
print(f'TCP>WS: {c}')
|
2024-08-27 22:00:08 +00:00
|
|
|
await websocket.send(c.to_bytes())
|
2024-08-27 19:44:15 +00:00
|
|
|
break
|
2024-08-27 22:00:08 +00:00
|
|
|
|
2024-08-27 21:21:22 +00:00
|
|
|
c = conn.WSMsg(socket_id, conn.MsgType.DATA, data)
|
2024-08-27 22:00:08 +00:00
|
|
|
print(f'TCP>WS: {c}')
|
2024-08-27 21:21:22 +00:00
|
|
|
await websocket.send(c.to_bytes())
|
|
|
|
|
2024-08-27 19:44:15 +00:00
|
|
|
# Forwarding data from WebSocket to client
|
|
|
|
async def websocket_to_client():
|
|
|
|
while True:
|
|
|
|
message = await websocket.recv()
|
2024-08-27 21:21:22 +00:00
|
|
|
c = conn.WSMsg.from_bytes(message)
|
|
|
|
|
|
|
|
# XXX this is ugly, because it means that the data is sent twice or more if 2+ connections..
|
2024-08-27 22:58:17 +00:00
|
|
|
print('c.socketid', c.socketid, 'socket_id', socket_id)
|
2024-08-27 20:26:35 +00:00
|
|
|
if c.socketid == socket_id:
|
2024-08-27 22:58:17 +00:00
|
|
|
print('ours')
|
2024-08-27 21:21:22 +00:00
|
|
|
if c.msg == conn.MsgType.DISCONNECT:
|
|
|
|
print(f"Client {socket_id} disconnected")
|
|
|
|
break
|
2024-08-27 22:00:08 +00:00
|
|
|
elif c.msg == conn.MsgType.CONNECT:
|
|
|
|
## This shouldn't really happen‽
|
|
|
|
break
|
2024-08-27 21:21:22 +00:00
|
|
|
else:
|
2024-08-27 22:00:08 +00:00
|
|
|
print(f'WS>TCP: {c}')
|
2024-08-27 21:21:22 +00:00
|
|
|
socket_writer.write(c.payload)
|
|
|
|
await socket_writer.drain()
|
|
|
|
else:
|
2024-08-27 22:58:17 +00:00
|
|
|
print('not ours')
|
2024-08-27 21:21:22 +00:00
|
|
|
print(f'WS>TCP@{socket_id}: ', hashlib.md5(message).hexdigest(), 'skipping')
|
|
|
|
|
|
|
|
|
2024-08-27 19:44:15 +00:00
|
|
|
# Run both tasks concurrently
|
|
|
|
await asyncio.gather(client_to_websocket(), websocket_to_client())
|
2024-08-27 21:21:22 +00:00
|
|
|
print(f">>>> Client {socket_id} disconnected")
|
2024-08-27 19:44:15 +00:00
|
|
|
|
2024-08-27 22:00:08 +00:00
|
|
|
finally:
|
|
|
|
print(f">>>>>>>>>> Closing client {socket_id}")
|
|
|
|
m = conn.WSMsg(socket_id, conn.MsgType.DISCONNECT)
|
|
|
|
await websocket.send(m.to_bytes())
|
|
|
|
|
|
|
|
socket_writer.close()
|
|
|
|
await socket_writer.wait_closed()
|
2024-08-27 19:44:15 +00:00
|
|
|
|
2024-08-27 22:05:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_config():
|
|
|
|
KUBE_API_PORT = os.environ.get('KUBE_API_PORT', DEFAULT_LISTEN_PORT)
|
|
|
|
|
|
|
|
if len(sys.argv) != 2:
|
|
|
|
print(f"Usage: {sys.argv[0]} <websocket_url>")
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
ws_url = sys.argv[1]
|
|
|
|
global WEBSOCKET_URL
|
|
|
|
# Yeah, I know this is fugly
|
|
|
|
WEBSOCKET_URL = ws_url
|
|
|
|
|
|
|
|
return {
|
|
|
|
'kube_api_port': KUBE_API_PORT,
|
|
|
|
'websocket_url': ws_url,
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2024-08-27 19:44:15 +00:00
|
|
|
async def main():
|
2024-08-27 22:05:41 +00:00
|
|
|
cfg = get_config()
|
|
|
|
|
|
|
|
try:
|
|
|
|
server = await asyncio.start_server(handle_client, LOCALHOST, cfg['kube_api_port'])
|
|
|
|
except OSError as e:
|
|
|
|
print(e)
|
|
|
|
print(f"There already is a client listening on port {cfg['kube_api_port']}")
|
|
|
|
sys.exit(1)
|
|
|
|
|
2024-08-27 19:44:15 +00:00
|
|
|
async with server:
|
2024-08-27 22:05:41 +00:00
|
|
|
print(f"Server started on {LOCALHOST} port {cfg['kube_api_port']}")
|
2024-08-27 19:44:15 +00:00
|
|
|
await server.serve_forever()
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
asyncio.run(main())
|
|
|
|
|
|
|
|
|
|
|
|
|