-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.py
More file actions
125 lines (100 loc) · 3.28 KB
/
Copy pathserver.py
File metadata and controls
125 lines (100 loc) · 3.28 KB
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import ssl
import json
import uuid
import asyncio
from websockets import ConnectionClosed
from websockets.asyncio.server import serve
HOST = "0.0.0.0"
PORT = 25565
ROOMS = {}
CLEAN = 60 # Seconds
SECURE = True
CERT = "cert.pem"
KEY = "key.pem"
async def clean_rooms():
while True:
print('Cleaning Vacant Rooms')
empty_rooms = []
for x in ROOMS:
if len(ROOMS[x]["connections"]) == 0:
empty_rooms.append(x)
for x in empty_rooms:
ROOMS.pop(x)
await asyncio.sleep(CLEAN)
def dump_json(obj):
try:
return json.dumps(obj)
except Exception as e:
print(e)
return {}
def load_json(_string):
try:
return json.loads(_string)
except Exception as e:
print(e)
return {}
def generate_room(websocket, room_id=None):
id = room_id or uuid.uuid4().hex
if ROOMS.get(id):
id = uuid.uuid4().hex
ROOMS[id] = {
"connections": [],
}
return id
def join_room(websocket, room_id):
if ROOMS.get(room_id):
if websocket not in ROOMS[room_id]["connections"]:
ROOMS[room_id]["connections"].append(websocket)
return True
return False
async def resolve_path(websocket, message):
if not message:
return
data = load_json(message)
match websocket.request.path:
case "/generate_room":
room_id = data.get("room_id")
if room_id:
await websocket.send(json.dumps({"room_id": generate_room(websocket, room_id)}))
else:
await websocket.send(json.dumps({"room_id": generate_room(websocket)}))
await websocket.close()
case "/client_endpoint":
room_id = data.get("room_id")
message = data.get("message")
if room_id and not message: # If there is a room id but no message, then connect
await websocket.send(json.dumps({"connected": join_room(websocket, room_id)}))
return
elif room_id and message: # If there is both a room and and id, send a message
for conn in ROOMS[room_id]["connections"]:
await conn.send(json.dumps({"message": message}))
return
async def handler(websocket):
try:
while True:
message = await websocket.recv()
if websocket.request.path == "/":
await websocket.send("Missing Path")
else:
await resolve_path(websocket, message)
except ConnectionClosed:
print("Client disconnected normally")
except Exception as e:
print(f"Unexpected error: {e}")
finally:
for x in ROOMS:
ROOMS[x]["connections"] = [
conn for conn in ROOMS[x]["connections"] if conn != websocket
]
async def main():
ssl_context = None
if SECURE:
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ssl_context.load_cert_chain(certfile=CERT, keyfile=KEY)
async with serve(handler, HOST, PORT, ssl=ssl_context):
print(f"Signalling Server Started on {HOST}:{PORT}")
print("Listening for connections...")
asyncio.create_task(clean_rooms())
await asyncio.Future()
if __name__ == "__main__":
asyncio.run(main())