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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +84 -104
app.py CHANGED
@@ -3,136 +3,116 @@ import os
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("/")
138
  def hello():
 
3
  from flask import Flask, request, jsonify
4
 
5
  app = Flask(__name__)
6
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
7
+ # ู…ุญุฑูƒ ุงุชุตุงู„: ุณูŠุฑูุฑ ุนุดูˆุงุฆูŠ ู…ู† peer_discovery + ู…ู†ุงูุฐ 0001..9999 ุจุงู„ุชุณู„ุณู„
8
+ # ูŠุชูˆู‚ู ูู‚ุท ุนู†ุฏ ุฃูˆู„ ุชุณุฌูŠู„ ู†ุงุฌุญ
9
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
10
+ import os, time, threading, socket, requests, importlib, random, sys
11
+
12
  CURRENT_SERVER = None
13
+ PORT = None
14
  CONNECTED = threading.Event()
 
15
 
16
+ def _load_peer_discovery():
 
17
  import peer_discovery as pd
18
  importlib.reload(pd)
19
+ return pd
20
+
21
+ def _pick_random_server(pd):
22
+ # ุฅู† ูƒุงู† ู„ุฏูŠูƒ pd.random_server() ุงุณุชุฎุฏู…ู‡ุŒ ูˆุฅู„ุง ุงุฎุชุฑ ุนุดูˆุงุฆูŠุงู‹ ู…ู† ุงู„ู‚ุงุฆู…ุฉ
23
+ if hasattr(pd, "random_server"):
24
+ return pd.random_server()
25
  servers = list(getattr(pd, "CENTRAL_REGISTRY_SERVERS", []))
26
+ if not servers:
27
+ raise RuntimeError("ู„ุง ุชูˆุฌุฏ ุณูŠุฑูุฑุงุช ููŠ peer_discovery.CENTRAL_REGISTRY_SERVERS")
28
+ random.shuffle(servers)
29
+ return servers[0]
30
+
31
+ def _get_local_ip(pd):
32
+ if hasattr(pd, "get_local_ip"):
33
+ return pd.get_local_ip()
34
+ # ุงุญุชูŠุงุท
35
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
36
+ try:
37
+ s.connect(("8.8.8.8", 80))
38
+ return s.getsockname()[0]
39
+ except Exception:
40
+ return "127.0.0.1"
41
+ finally:
42
+ s.close()
43
+
44
+ def _lan_port(pd):
45
+ return int(getattr(pd, "LAN_PORT", os.getenv("LAN_PORT", 7520)))
46
+
47
+ def _can_bind_low_ports():
48
+ # ุนู„ู‰ ู„ูŠู†ูƒุณ: ุชุญุชุงุฌ root ู„ู„ู…ู†ุงูุฐ <1024
49
+ if os.name != "nt":
50
+ try:
51
+ return os.geteuid() == 0 # type: ignore[attr-defined]
52
+ except Exception:
53
+ return False
54
+ return True # ูˆูŠู†ุฏูˆุฒ ุนุงุฏุฉ ูŠุณู…ุญ
55
+
56
+ def _is_port_free(port, host="0.0.0.0"):
57
  with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
58
  s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
59
  try:
60
+ s.bind((host, int(port)))
61
  return True
62
  except OSError:
63
  return False
64
 
65
+ def _try_register(server, port, node_id, ip):
66
+ payload = {"node_id": node_id, "ip": ip, "port": int(port)}
67
+ r = requests.post(f"{server}/register", json=payload, timeout=6)
68
+ r.raise_for_status()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
 
70
+ def _sequential_ports(pd):
71
+ """ูŠูˆู„ู‘ุฏ 0001..9999 ู…ุน ู…ุฑุงุนุงุฉ ุงู„ู€ LAN_PORT ูˆุชุฎุทูŠ <1024 ุฅุฐุง ุบูŠุฑ ู…ุณู…ูˆุญ."""
72
+ lan_p = _lan_port(pd)
73
+ start = 1 if _can_bind_low_ports() else 1025
74
+ for p in range(start, 10000):
75
+ if p == lan_p:
76
+ continue
77
+ yield p
78
 
79
  def _connect_until_success():
80
+ global CURRENT_SERVER, PORT
81
  backoff = 1
82
  while True:
83
+ pd = _load_peer_discovery()
84
+ server = _pick_random_server(pd)
85
+ node_id = os.getenv("NODE_ID", socket.gethostname())
86
+ ip = _get_local_ip(pd)
87
+ print(f"๐Ÿ”Ž Trying server: {server}")
88
+
89
+ any_attempt = False
90
+ for p in _sequential_ports(pd):
91
+ any_attempt = True
92
+ if not _is_port_free(p):
93
+ continue
94
+ try:
95
+ _try_register(server, p, node_id, ip)
96
+ CURRENT_SERVER, PORT = server, int(p)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  CONNECTED.set()
98
+ print(f"โœ… Connected to {server} with port {PORT:04d}")
99
  return
100
+ except Exception as e:
101
+ # ุงุทุจุน ุนู„ู‰ ูุชุฑุงุช ู„ุชุฌู†ุจ ุงู„ุถูˆุถุงุก
102
+ if p % 1000 == 0:
103
+ print(f"โ€ฆstill scanning (last error on {server}:{p:04d}) -> {e}")
104
 
105
+ # ู„ู… ูŠู†ุฌุญ ุฃูŠ ู…ู†ูุฐ ู…ุน ู‡ุฐุง ุงู„ุณูŠุฑูุฑ โ†’ ุฌุฑู‘ุจ ุณูŠุฑูุฑ ุฌุฏูŠุฏ
106
+ if not any_attempt:
107
+ print("โš ๏ธ ู„ู… ุชูุฌุฑูŽ ู…ุญุงูˆู„ุงุช ู…ู†ุงูุฐ (ุชุญู‚ู‚ ู…ู† ุตู„ุงุญูŠุงุช ุงู„ู…ู†ุงูุฐ ุงู„ู…ู†ุฎูุถุฉ).")
108
+
109
+ print(f"โ†ป No success on {server}. Picking a new serverโ€ฆ")
110
  time.sleep(backoff)
111
+ backoff = min(backoff * 2, 10) # backoff ุจุณูŠุท ู„ุชุฎููŠู ุงู„ุถุบุท
112
 
113
  def start_connect_loop():
114
  threading.Thread(target=_connect_until_success, daemon=True).start()
115
 
 
 
 
 
116
  # ู…ุณุงุฑ ุงุฎุชุจุงุฑ ุณุฑูŠุน
117
  @app.get("/")
118
  def hello():