osamabyc86 commited on
Commit
3970cb9
ยท
verified ยท
1 Parent(s): cdfe90a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +129 -0
app.py CHANGED
@@ -3,6 +3,135 @@ import os
3
  from flask import Flask, request, jsonify
4
 
5
  app = Flask(__name__)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
  # ู…ุณุงุฑ ุงุฎุชุจุงุฑ ุณุฑูŠุน
8
  @app.get("/")
 
3
  from flask import Flask, request, jsonify
4
 
5
  app = Flask(__name__)
6
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
7
+ # ู…ุญุฑูƒ ุงุชุตุงู„ ุฎุงุฑุฌูŠ: Direct ุฃูˆู„ุงู‹ุŒ ุซู… Relay (WebSocket) ูƒุฎุทุฉ B
8
+ # ุฃู„ุตู‚ู‡ ุจุนุฏ ุงู„ุงุณุชูŠุฑุงุฏุงุช ูˆู‚ุจู„ ุจุฏุก ุฎุฏุงู…ูƒ (RPC/Flask)
9
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
10
+ import os, time, threading, socket, random, requests, importlib
11
+ MODE = None # "direct" ุฃูˆ "relay"
12
+ CURRENT_SERVER = None
13
+ PORT = None # ู…ู†ูุฐูƒ ุงู„ู…ุญู„ูŠ ู„ุฎุฏู…ุฉ /run ุฃูˆ RPC
14
+ CONNECTED = threading.Event()
15
+ RELAY_SIO = None
16
+
17
+ # โ† ุฌูุจ ุงู„ู…ุฑุดุญูŠู† ู…ู† peer_discovery ููŠ ูƒู„ ุฏูˆุฑุฉ (ุญุชู‰ ู„ูˆ ุจูŠูˆู„ุฏู‡ู… ุฏูŠู†ุงู…ูŠูƒูŠุงู‹)
18
+ def _load_candidates():
19
+ import peer_discovery as pd
20
+ importlib.reload(pd)
21
+ servers = list(getattr(pd, "CENTRAL_REGISTRY_SERVERS", []))
22
+ # ู…ู†ูุฐูƒ ุงู„ุฐูŠ ุณุชุดุบู„ ุนู„ูŠู‡ ุงู„ู€ RPC ู…ุญู„ูŠู‹ุง (ูˆู„ูŠุณ ู…ู†ูุฐ ุงู„ุณูŠุฑูุฑ ุงู„ุนุงู…)
23
+ # ูŠูุถู„ ุฃู† ูŠูƒูˆู† ู…ุง ูŠูˆู„ุฏู‡ peer_discoveryุ› ูˆุฅู† ู„ู… ูŠูˆุฌุฏ ุงุณุชุฎุฏู… 7860/8000/5000 ุงุญุชูŠุงุท
24
+ ports = list(getattr(pd, "rport", [])) or ["7860", "8000", "5000"]
25
+ get_ip = getattr(pd, "get_local_ip", lambda: "127.0.0.1")
26
+ random.shuffle(servers); random.shuffle(ports)
27
+ return servers, [int(p) for p in ports], get_ip
28
+
29
+ def _is_port_free(p, host="0.0.0.0"):
30
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
31
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
32
+ try:
33
+ s.bind((host, int(p)))
34
+ return True
35
+ except OSError:
36
+ return False
37
+
38
+ def _try_direct_register(server, port, get_ip):
39
+ """
40
+ ูŠุญุงูˆู„ ุงู„ุชุณุฌูŠู„ ุงู„ู…ุจุงุดุฑ ุนู†ุฏ ุงู„ุณูŠุฑูุฑ: POST /register
41
+ ุฅุฐุง ู†ุฌุญุŒ ู†ุณุชุฎุฏู… ู‡ุฐุง ุงู„ู…ู†ูุฐ ู„ุชุดุบูŠู„ ุฎุงุฏู…ู†ุง ุงู„ู…ุญู„ูŠ ู„ุงุญู‚ู‹ุง.
42
+ """
43
+ info = {
44
+ "node_id": os.getenv("NODE_ID", socket.gethostname()),
45
+ "ip": get_ip(),
46
+ "port": int(port),
47
+ }
48
+ r = requests.post(f"{server}/register", json=info, timeout=6)
49
+ r.raise_for_status() # ูŠุฑู…ูŠ ุงุณุชุซู†ุงุก ู„ูˆ ูุดู„
50
+ return True
51
+
52
+ def _start_relay_client(server):
53
+ """
54
+ ูˆุถุน Relay: ู‚ู†ุงุฉ Socket.IO ุฏุงุฆู…ุฉ ู…ุน ุงู„ุณูŠุฑูุฑ (ุนู„ู‰ 443 ุบุงู„ุจู‹ุง).
55
+ ู„ุง ุชุญุชุงุฌ ุฃูŠ ู…ู†ูุฐ inbound. ุฅุฐุง ุงู„ุณูŠุฑูุฑ ูŠุฏุนู… relayุŒ ูŠูุนุชุจุฑ ุงุชุตุงู„ ุฎุงุฑุฌูŠ ู†ุงุฌุญ.
56
+ """
57
+ global RELAY_SIO
58
+ import socketio # python-socketio client
59
+ sio = socketio.Client(reconnection=True, reconnection_attempts=0)
60
+
61
+ node_id = os.getenv("NODE_ID", socket.gethostname())
62
+
63
+ @sio.event
64
+ def connect():
65
+ print(f"๐Ÿ”Œ Relay connected to {server}")
66
+ sio.emit("register_node", {"node_id": node_id})
67
+ # ุงุนุชุจุฑ ุงู„ุงุชุตุงู„ ู†ุงุฌุญ ุฎุงุฑุฌูŠู‹ุง
68
+ # ู†ูุจู‚ูŠ PORT ู„ุงุณุชุฎุฏุงู… LAN/RPC ู…ุญู„ูŠ (ู„ูˆ ุงุญุชุฌุชู‡). ุชุณุชุทูŠุน ุถุจุทู‡ ู„ุงุญู‚ู‹ุง.
69
+
70
+ @sio.event
71
+ def disconnect():
72
+ print("โš ๏ธ Relay disconnected; will auto-reconnectโ€ฆ")
73
+
74
+ # ุฃู…ุซู„ุฉ ุฃุญุฏุงุซ (ุนุฏู‘ู„ ุนู„ู‰ ู…ุฒุงุฌูƒ):
75
+ @sio.on("ping_node")
76
+ def _on_ping(msg):
77
+ sio.emit("pong_node", {"node_id": node_id, "t": time.time()})
78
+
79
+ try:
80
+ # Socket.IO URL โ† ุนุงุฏุฉ ู†ูุณ ุงู„ุฏูˆู…ูŠู† ุนู„ู‰ /socket.io
81
+ sio.connect(server, transports=["websocket", "polling"], wait_timeout=10)
82
+ RELAY_SIO = sio
83
+ return True
84
+ except Exception as e:
85
+ print(f"โŒ Relay connect failed: {e}")
86
+ return False
87
+
88
+ def _connect_until_success():
89
+ global MODE, CURRENT_SERVER, PORT
90
+ backoff = 1
91
+ while True:
92
+ servers, ports, get_ip = _load_candidates()
93
+
94
+ # 1) ุฌุฑู‘ุจ DIRECT ุนู„ู‰ ูƒู„ ุงู„ุณูŠุฑูุฑุงุช ู…ุน ู…ุฌู…ูˆุนุฉ ู…ู†ุงูุฐูƒ
95
+ for s in servers:
96
+ for p in ports:
97
+ # ุชุฃูƒุฏ ุฃู† ุงู„ู…ู†ูุฐ ู…ุชุงุญ ู…ุญู„ูŠู‹ุง ู„ุชุดุบูŠู„ ุฎุงุฏู…ูƒ ู„ุงุญู‚ู‹ุง
98
+ if not _is_port_free(p):
99
+ continue
100
+ try:
101
+ _try_direct_register(s, p, get_ip)
102
+ MODE, CURRENT_SERVER, PORT = "direct", s, int(p)
103
+ print(f"โœ… DIRECT connected: {s} (node port {PORT})")
104
+ CONNECTED.set()
105
+ return
106
+ except Exception as e:
107
+ print(f"โš ๏ธ DIRECT failed on {s} / {p}: {e}")
108
+
109
+ # 2) ุฅุฐุง ูุดู„ุช ุงู„ู…ุจุงุดุฑุฉ ุนู„ู‰ ุงู„ูƒู„ โ†’ ุฌุฑู‘ุจ RELAY ู„ูƒู„ ุณูŠุฑูุฑ ุจุงู„ุชุฑุชูŠุจ
110
+ for s in servers:
111
+ ok = _start_relay_client(s)
112
+ if ok:
113
+ MODE, CURRENT_SERVER = "relay", s
114
+ # PORT ุงุฎุชูŠุงุฑูŠ ู‡ู†ุง (ู„ู€ LAN ูู‚ุท). ู„ูˆ ุนู†ุฏูƒ RPC ู…ุญู„ู‘ูŠ ุดุบู‘ู„ู‡ ุนู„ู‰ ุฃูŠ ู…ู†ูุฐ ู…ุชุงุญ.
115
+ if ports:
116
+ # ุงุฎุชุฑ ุฃูˆู„ ู…ู†ูุฐ ู…ุชุงุญ ู…ุญู„ูŠู‹ุง ู„ู„ุชุดุบูŠู„ ุงู„ุฏุงุฎู„ูŠ
117
+ for p in ports:
118
+ if _is_port_free(p):
119
+ PORT = int(p)
120
+ break
121
+ print(f"โœ… RELAY connected via {s} (no inbound port needed)")
122
+ CONNECTED.set()
123
+ return
124
+
125
+ # ู„ุง ู†ุฌุงุญ ุจุนุฏ ุงู„ุชุฌุฑุจุชูŠู† โ†’ ุงู†ุชุธุฑ ูˆุฒูุฏ ุงู„ู…ู‡ู„ุฉ ูˆุฃุนุฏ ุงู„ู…ุญุงูˆู„ุฉ
126
+ time.sleep(backoff)
127
+ backoff = min(backoff * 2, 30)
128
+
129
+ def start_connect_loop():
130
+ threading.Thread(target=_connect_until_success, daemon=True).start()
131
+
132
+ # ุดุบู‘ู„ ุญู„ู‚ุฉ ุงู„ุงุชุตุงู„ ู…ุจูƒุฑู‹ุง:
133
+ start_connect_loop()
134
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
135
 
136
  # ู…ุณุงุฑ ุงุฎุชุจุงุฑ ุณุฑูŠุน
137
  @app.get("/")