kylsprt commited on
Commit
aa34189
·
verified ·
1 Parent(s): d41e7ae

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +39 -6
main.py CHANGED
@@ -4,10 +4,24 @@ from pathlib import Path
4
  import uvicorn
5
  import json
6
  import uuid
 
 
 
 
7
 
8
  app = FastAPI()
9
  rooms = {}
10
 
 
 
 
 
 
 
 
 
 
 
11
 
12
  @app.get("/")
13
  async def index():
@@ -19,6 +33,11 @@ async def ping():
19
  return {"status": "alive"}
20
 
21
 
 
 
 
 
 
22
  @app.websocket("/ws/{room}")
23
  async def ws_endpoint(websocket: WebSocket, room: str):
24
  await websocket.accept()
@@ -27,6 +46,7 @@ async def ws_endpoint(websocket: WebSocket, room: str):
27
  rooms[room] = {"peers": {}, "broadcaster": None}
28
  r = rooms[room]
29
  r["peers"][pid] = websocket
 
30
  await websocket.send_text(json.dumps({"type": "assigned", "id": pid}))
31
  await broadcast_state(room)
32
  try:
@@ -42,12 +62,14 @@ async def ws_endpoint(websocket: WebSocket, room: str):
42
  if tag == 2 and r["broadcaster"] != pid:
43
  continue
44
  await relay_bytes(room, pid, raw)
45
- except (WebSocketDisconnect, Exception):
 
46
  r["peers"].pop(pid, None)
47
  if r["broadcaster"] == pid:
48
  r["broadcaster"] = None
49
  if not r["peers"]:
50
  rooms.pop(room, None)
 
51
  else:
52
  await notify_leave(room, pid)
53
  await broadcast_state(room)
@@ -61,6 +83,7 @@ async def handle_text(room, sender, data):
61
  if t == "set_broadcaster":
62
  old = r["broadcaster"]
63
  r["broadcaster"] = sender
 
64
  if old and old != sender and old in r["peers"]:
65
  try:
66
  await r["peers"][old].send_text(json.dumps({"type": "force_viewer"}))
@@ -70,16 +93,22 @@ async def handle_text(room, sender, data):
70
  elif t == "set_viewer":
71
  if r["broadcaster"] == sender:
72
  r["broadcaster"] = None
 
73
  await broadcast_state(room)
74
- elif t in ("offer", "answer", "ice"):
75
  target = data.get("to")
76
- if target and target in r["peers"]:
 
 
77
  fwd = dict(data)
78
  fwd["from"] = sender
79
  try:
80
  await r["peers"][target].send_text(json.dumps(fwd))
81
- except:
82
- pass
 
 
 
83
 
84
 
85
  async def relay_bytes(room, sender, data):
@@ -95,12 +124,14 @@ async def relay_bytes(room, sender, data):
95
  dead.append(pid)
96
  for d in dead:
97
  r["peers"].pop(d, None)
 
98
 
99
 
100
  async def broadcast_state(room):
101
  r = rooms.get(room)
102
  if not r:
103
  return
 
104
  for pid, ws in list(r["peers"].items()):
105
  try:
106
  await ws.send_text(json.dumps({
@@ -112,7 +143,9 @@ async def broadcast_state(room):
112
  "is_broadcaster": pid == r["broadcaster"]
113
  }))
114
  except:
115
- r["peers"].pop(pid, None)
 
 
116
 
117
 
118
  async def notify_leave(room, pid):
 
4
  import uvicorn
5
  import json
6
  import uuid
7
+ import logging
8
+
9
+ logging.basicConfig(level=logging.INFO)
10
+ log = logging.getLogger("intercom")
11
 
12
  app = FastAPI()
13
  rooms = {}
14
 
15
+ ICE_SERVERS = [
16
+ {"urls": "stun:stun.l.google.com:19302"},
17
+ {"urls": "stun:stun1.l.google.com:19302"},
18
+ {"urls": "stun:stun2.l.google.com:19302"},
19
+ {"urls": "stun:stun3.l.google.com:19302"},
20
+ {"urls": "turn:openrelay.metered.ca:80", "username": "openrelayproject", "credential": "openrelayproject"},
21
+ {"urls": "turn:openrelay.metered.ca:443", "username": "openrelayproject", "credential": "openrelayproject"},
22
+ {"urls": "turn:openrelay.metered.ca:443?transport=tcp", "username": "openrelayproject", "credential": "openrelayproject"},
23
+ ]
24
+
25
 
26
  @app.get("/")
27
  async def index():
 
33
  return {"status": "alive"}
34
 
35
 
36
+ @app.get("/ice")
37
+ async def get_ice():
38
+ return {"iceServers": ICE_SERVERS}
39
+
40
+
41
  @app.websocket("/ws/{room}")
42
  async def ws_endpoint(websocket: WebSocket, room: str):
43
  await websocket.accept()
 
46
  rooms[room] = {"peers": {}, "broadcaster": None}
47
  r = rooms[room]
48
  r["peers"][pid] = websocket
49
+ log.info(f"[+] {pid} joined '{room}' ({len(r['peers'])} peers)")
50
  await websocket.send_text(json.dumps({"type": "assigned", "id": pid}))
51
  await broadcast_state(room)
52
  try:
 
62
  if tag == 2 and r["broadcaster"] != pid:
63
  continue
64
  await relay_bytes(room, pid, raw)
65
+ except (WebSocketDisconnect, Exception) as e:
66
+ log.info(f"[-] {pid} left '{room}': {type(e).__name__}")
67
  r["peers"].pop(pid, None)
68
  if r["broadcaster"] == pid:
69
  r["broadcaster"] = None
70
  if not r["peers"]:
71
  rooms.pop(room, None)
72
+ log.info(f"[x] Room '{room}' removed (empty)")
73
  else:
74
  await notify_leave(room, pid)
75
  await broadcast_state(room)
 
83
  if t == "set_broadcaster":
84
  old = r["broadcaster"]
85
  r["broadcaster"] = sender
86
+ log.info(f"[B] {sender} broadcasting in '{room}'")
87
  if old and old != sender and old in r["peers"]:
88
  try:
89
  await r["peers"][old].send_text(json.dumps({"type": "force_viewer"}))
 
93
  elif t == "set_viewer":
94
  if r["broadcaster"] == sender:
95
  r["broadcaster"] = None
96
+ log.info(f"[V] {sender} stopped broadcasting in '{room}'")
97
  await broadcast_state(room)
98
+ elif t in ("offer", "answer", "ice", "negotiate"):
99
  target = data.get("to")
100
+ if not target:
101
+ return
102
+ if target in r["peers"]:
103
  fwd = dict(data)
104
  fwd["from"] = sender
105
  try:
106
  await r["peers"][target].send_text(json.dumps(fwd))
107
+ log.info(f"[S] {t} from {sender} -> {target}")
108
+ except Exception as e:
109
+ log.warning(f"[!] Signal fail {t} {sender}->{target}: {e}")
110
+ elif t == "p2p_failed":
111
+ log.info(f"[!] P2P failed for {sender} in '{room}', falling back to relay")
112
 
113
 
114
  async def relay_bytes(room, sender, data):
 
124
  dead.append(pid)
125
  for d in dead:
126
  r["peers"].pop(d, None)
127
+ log.info(f"[-] {d} dead connection removed from '{room}'")
128
 
129
 
130
  async def broadcast_state(room):
131
  r = rooms.get(room)
132
  if not r:
133
  return
134
+ dead = []
135
  for pid, ws in list(r["peers"].items()):
136
  try:
137
  await ws.send_text(json.dumps({
 
143
  "is_broadcaster": pid == r["broadcaster"]
144
  }))
145
  except:
146
+ dead.append(pid)
147
+ for d in dead:
148
+ r["peers"].pop(d, None)
149
 
150
 
151
  async def notify_leave(room, pid):