Alvin3y1 commited on
Commit
8f006d4
·
verified ·
1 Parent(s): 9599663

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +38 -17
app.py CHANGED
@@ -8,23 +8,20 @@ from aiohttp import web
8
  from aiortc import RTCPeerConnection, RTCSessionDescription, RTCIceServer, RTCConfiguration
9
 
10
  logging.basicConfig(level=logging.INFO)
11
- logger = logging.getLogger("BuiltVNC-Bridge")
12
 
 
13
  VNC_PORT = 5900
 
 
 
14
 
15
  def start_system():
16
  os.environ["DISPLAY"] = ":99"
17
-
18
- # 1. Start Xvfb
19
  subprocess.Popen(["Xvfb", ":99", "-screen", "0", "1280x720x24", "-ac"])
20
  time.sleep(1)
21
-
22
- # 2. Start YOUR BUILT VNC TOOL
23
- logger.info("Starting custom built minivnc...")
24
  subprocess.Popen(["/usr/local/bin/minivnc"])
25
  time.sleep(1)
26
-
27
- # 3. Start Window Manager & Opera
28
  subprocess.Popen("matchbox-window-manager -use_titlebar no", shell=True)
29
  subprocess.Popen("opera --no-sandbox --user-data-dir=/home/user/opera-data", shell=True)
30
 
@@ -36,29 +33,53 @@ async def bridge_vnc(channel):
36
  data = await reader.read(65536)
37
  if not data: break
38
  channel.send(data)
39
-
40
  @channel.on("message")
41
  def on_message(msg):
42
  if isinstance(msg, bytes): writer.write(msg)
43
-
44
  await vnc_to_rtc()
45
  except Exception as e: logger.error(f"Bridge fail: {e}")
46
 
47
  async def offer(request):
48
  params = await request.json()
49
- pc = RTCPeerConnection() # Simplified for brevity, add TURN if needed
 
 
 
 
 
 
 
 
 
50
  @pc.on("datachannel")
51
  def on_dc(channel):
52
  asyncio.create_task(bridge_vnc(channel))
53
-
54
  await pc.setRemoteDescription(RTCSessionDescription(sdp=params["sdp"], type=params["type"]))
55
- await pc.setLocalDescription(await pc.createAnswer())
56
- return web.Response(content_type="application/json", text=json.dumps({
57
- "sdp": pc.localDescription.sdp, "type": pc.localDescription.type
58
- }), headers={"Access-Control-Allow-Origin": "*"})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
 
60
  if __name__ == "__main__":
61
  start_system()
62
  app = web.Application()
63
  app.router.add_post("/offer", offer)
64
- web.run_app(app, port=7860)
 
 
8
  from aiortc import RTCPeerConnection, RTCSessionDescription, RTCIceServer, RTCConfiguration
9
 
10
  logging.basicConfig(level=logging.INFO)
11
+ logger = logging.getLogger("HF-VNC-Bridge")
12
 
13
+ # Configuration
14
  VNC_PORT = 5900
15
+ # Cloudflare TURN helps bypass Hugging Face's strict network/firewall
16
+ TURN_USER = "g08abe68c81a07f098bb5f0914549bb32440e5aad0b216c7fba2b61e76fd62c6"
17
+ TURN_PASS = "aed1a10dd10eba9401ad9d99e5c66036d8a970eab5ba8e6dc9845ab57c771a7d"
18
 
19
  def start_system():
20
  os.environ["DISPLAY"] = ":99"
 
 
21
  subprocess.Popen(["Xvfb", ":99", "-screen", "0", "1280x720x24", "-ac"])
22
  time.sleep(1)
 
 
 
23
  subprocess.Popen(["/usr/local/bin/minivnc"])
24
  time.sleep(1)
 
 
25
  subprocess.Popen("matchbox-window-manager -use_titlebar no", shell=True)
26
  subprocess.Popen("opera --no-sandbox --user-data-dir=/home/user/opera-data", shell=True)
27
 
 
33
  data = await reader.read(65536)
34
  if not data: break
35
  channel.send(data)
 
36
  @channel.on("message")
37
  def on_message(msg):
38
  if isinstance(msg, bytes): writer.write(msg)
 
39
  await vnc_to_rtc()
40
  except Exception as e: logger.error(f"Bridge fail: {e}")
41
 
42
  async def offer(request):
43
  params = await request.json()
44
+
45
+ # Crucial: Use ICE Servers for remote connection
46
+ config = RTCConfiguration(iceServers=[
47
+ RTCIceServer(urls=["stun:stun.l.google.com:19302"]),
48
+ RTCIceServer(urls=["turns:turn.cloudflare.com:443?transport=tcp"], username=TURN_USER, credential=TURN_PASS)
49
+ ])
50
+
51
+ pc = RTCPeerConnection(config)
52
+ pcs.add(pc)
53
+
54
  @pc.on("datachannel")
55
  def on_dc(channel):
56
  asyncio.create_task(bridge_vnc(channel))
57
+
58
  await pc.setRemoteDescription(RTCSessionDescription(sdp=params["sdp"], type=params["type"]))
59
+ answer = await pc.createAnswer()
60
+ await pc.setLocalDescription(answer)
61
+
62
+ return web.Response(
63
+ content_type="application/json",
64
+ text=json.dumps({"sdp": pc.localDescription.sdp, "type": pc.localDescription.type}),
65
+ headers={
66
+ "Access-Control-Allow-Origin": "*", # Allow connections from your other site
67
+ "Access-Control-Allow-Methods": "POST, OPTIONS",
68
+ "Access-Control-Allow-Headers": "Content-Type"
69
+ }
70
+ )
71
+
72
+ async def options(request):
73
+ return web.Response(headers={
74
+ "Access-Control-Allow-Origin": "*",
75
+ "Access-Control-Allow-Methods": "POST, OPTIONS",
76
+ "Access-Control-Allow-Headers": "Content-Type"
77
+ })
78
 
79
+ pcs = set()
80
  if __name__ == "__main__":
81
  start_system()
82
  app = web.Application()
83
  app.router.add_post("/offer", offer)
84
+ app.router.add_options("/offer", options)
85
+ web.run_app(app, host="0.0.0.0", port=7860)