GitHub Action
commited on
Commit
·
ca99925
1
Parent(s):
4122434
Sync from GitHub with Git LFS
Browse files- agents/peer_sync.py +80 -39
agents/peer_sync.py
CHANGED
|
@@ -165,6 +165,31 @@ def start_peer_services(port):
|
|
| 165 |
def udp_discovery(sock, local_ports):
|
| 166 |
"""Приём и рассылка discovery через один сокет (IPv4+IPv6)."""
|
| 167 |
DISCOVERY_INTERVAL = 30
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 168 |
|
| 169 |
while True:
|
| 170 |
# --- Приём сообщений ---
|
|
@@ -172,8 +197,21 @@ def udp_discovery(sock, local_ports):
|
|
| 172 |
rlist, _, _ = select.select([sock], [], [], 0.5)
|
| 173 |
for s in rlist:
|
| 174 |
try:
|
| 175 |
-
data, addr = s.recvfrom(
|
| 176 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 177 |
peer_id = msg.get("id")
|
| 178 |
if peer_id == my_id:
|
| 179 |
continue
|
|
@@ -195,7 +233,7 @@ def udp_discovery(sock, local_ports):
|
|
| 195 |
"addr": storage.normalize_address(a),
|
| 196 |
"nonce": None,
|
| 197 |
"pow_hash": None,
|
| 198 |
-
"datetime": datetime.now(
|
| 199 |
})
|
| 200 |
|
| 201 |
storage.add_or_update_peer(
|
|
@@ -209,6 +247,18 @@ def udp_discovery(sock, local_ports):
|
|
| 209 |
except Exception as e:
|
| 210 |
print(f"[UDP Discovery] select() error: {e}")
|
| 211 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 212 |
# --- Формируем локальные адреса для рассылки ---
|
| 213 |
local_addresses = []
|
| 214 |
for iface in netifaces.interfaces():
|
|
@@ -219,24 +269,19 @@ def udp_discovery(sock, local_ports):
|
|
| 219 |
"addr": storage.normalize_address(f"any://{ip}:{local_ports[0]}"),
|
| 220 |
"nonce": 0,
|
| 221 |
"pow_hash": "0"*64,
|
| 222 |
-
"datetime": datetime.now(
|
| 223 |
-
})
|
| 224 |
-
for a in netifaces.ifaddresses(iface).get(netifaces.AF_INET6, []):
|
| 225 |
-
ip = a.get("addr")
|
| 226 |
-
if ip:
|
| 227 |
-
local_addresses.append({
|
| 228 |
-
"addr": storage.normalize_address(f"any://[{ip}]:{local_ports[0]}"),
|
| 229 |
-
"nonce": 0,
|
| 230 |
-
"pow_hash": "0"*64,
|
| 231 |
-
"datetime": datetime.now(UTC).replace(microsecond=0).isoformat()
|
| 232 |
})
|
| 233 |
|
| 234 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 235 |
"id": my_id,
|
| 236 |
"name": agent_name,
|
| 237 |
"addresses": local_addresses,
|
| 238 |
"pubkey": my_pubkey
|
| 239 |
-
}
|
| 240 |
|
| 241 |
for port in local_ports:
|
| 242 |
# IPv4 broadcast
|
|
@@ -244,30 +289,26 @@ def udp_discovery(sock, local_ports):
|
|
| 244 |
addrs = netifaces.ifaddresses(iface).get(netifaces.AF_INET, [])
|
| 245 |
for a in addrs:
|
| 246 |
if "broadcast" in a:
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
|
| 250 |
-
|
| 251 |
-
|
| 252 |
-
|
| 253 |
-
|
| 254 |
-
|
| 255 |
-
#
|
| 256 |
-
|
| 257 |
-
|
| 258 |
-
|
| 259 |
-
|
| 260 |
-
|
| 261 |
-
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
m_sock.sendto(msg_data, (multicast_addr, port))
|
| 268 |
-
m_sock.close()
|
| 269 |
-
except Exception as e:
|
| 270 |
-
print(f"[UDP Discovery] IPv6 send error on {iface}:{port} -> {e}")
|
| 271 |
|
| 272 |
time.sleep(DISCOVERY_INTERVAL)
|
| 273 |
|
|
|
|
| 165 |
def udp_discovery(sock, local_ports):
|
| 166 |
"""Приём и рассылка discovery через один сокет (IPv4+IPv6)."""
|
| 167 |
DISCOVERY_INTERVAL = 30
|
| 168 |
+
MAX_PACKET_SIZE = 1200 # безопасный лимит под UDP
|
| 169 |
+
chunks_buffer = {} # addr -> {chunk_idx: data, total: n}
|
| 170 |
+
|
| 171 |
+
def send_discovery_packets(msg_dict, dest, port):
|
| 172 |
+
"""Разбивка JSON на чанки и отправка по UDP."""
|
| 173 |
+
msg_json = json.dumps(msg_dict)
|
| 174 |
+
chunks = [msg_json[i:i + MAX_PACKET_SIZE] for i in range(0, len(msg_json), MAX_PACKET_SIZE)]
|
| 175 |
+
total = len(chunks)
|
| 176 |
+
for idx, chunk in enumerate(chunks):
|
| 177 |
+
pkt = json.dumps({
|
| 178 |
+
"chunk": idx,
|
| 179 |
+
"total": total,
|
| 180 |
+
"data": chunk
|
| 181 |
+
}).encode("utf-8")
|
| 182 |
+
try:
|
| 183 |
+
if ":" not in dest: # IPv4
|
| 184 |
+
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
| 185 |
+
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) # 👈 включаем broadcast
|
| 186 |
+
else: # IPv6
|
| 187 |
+
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
|
| 188 |
+
|
| 189 |
+
s.sendto(pkt, (dest, port))
|
| 190 |
+
s.close()
|
| 191 |
+
except Exception as e:
|
| 192 |
+
print(f"[UDP Discovery] send error to {dest}:{port} -> {e}")
|
| 193 |
|
| 194 |
while True:
|
| 195 |
# --- Приём сообщений ---
|
|
|
|
| 197 |
rlist, _, _ = select.select([sock], [], [], 0.5)
|
| 198 |
for s in rlist:
|
| 199 |
try:
|
| 200 |
+
data, addr = s.recvfrom(4096)
|
| 201 |
+
pkt = json.loads(data.decode("utf-8"))
|
| 202 |
+
|
| 203 |
+
if "chunk" in pkt and "total" in pkt and "data" in pkt:
|
| 204 |
+
buf = chunks_buffer.setdefault(addr, {"chunks": {}, "total": pkt["total"]})
|
| 205 |
+
buf["chunks"][pkt["chunk"]] = pkt["data"]
|
| 206 |
+
if len(buf["chunks"]) == buf["total"]:
|
| 207 |
+
full_msg_json = "".join(buf["chunks"][i] for i in range(buf["total"]))
|
| 208 |
+
msg = json.loads(full_msg_json)
|
| 209 |
+
del chunks_buffer[addr]
|
| 210 |
+
else:
|
| 211 |
+
continue
|
| 212 |
+
else:
|
| 213 |
+
msg = pkt # старый формат
|
| 214 |
+
|
| 215 |
peer_id = msg.get("id")
|
| 216 |
if peer_id == my_id:
|
| 217 |
continue
|
|
|
|
| 233 |
"addr": storage.normalize_address(a),
|
| 234 |
"nonce": None,
|
| 235 |
"pow_hash": None,
|
| 236 |
+
"datetime": datetime.now(timezone.utc).replace(microsecond=0).isoformat()
|
| 237 |
})
|
| 238 |
|
| 239 |
storage.add_or_update_peer(
|
|
|
|
| 247 |
except Exception as e:
|
| 248 |
print(f"[UDP Discovery] select() error: {e}")
|
| 249 |
|
| 250 |
+
# --- Вывод интерфейсов и их адресов ---
|
| 251 |
+
print("[UDP Discovery] Interfaces:")
|
| 252 |
+
for iface in netifaces.interfaces():
|
| 253 |
+
addrs = netifaces.ifaddresses(iface)
|
| 254 |
+
ipv4_list = addrs.get(netifaces.AF_INET, [])
|
| 255 |
+
ipv6_list = addrs.get(netifaces.AF_INET6, [])
|
| 256 |
+
try:
|
| 257 |
+
if_idx = socket.if_nametoindex(iface)
|
| 258 |
+
except Exception:
|
| 259 |
+
if_idx = None
|
| 260 |
+
print(f" {iface} (idx={if_idx}) - IPv4: {ipv4_list}, IPv6: {ipv6_list}")
|
| 261 |
+
|
| 262 |
# --- Формируем локальные адреса для рассылки ---
|
| 263 |
local_addresses = []
|
| 264 |
for iface in netifaces.interfaces():
|
|
|
|
| 269 |
"addr": storage.normalize_address(f"any://{ip}:{local_ports[0]}"),
|
| 270 |
"nonce": 0,
|
| 271 |
"pow_hash": "0"*64,
|
| 272 |
+
"datetime": datetime.now(timezone.utc).replace(microsecond=0).isoformat()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 273 |
})
|
| 274 |
|
| 275 |
+
# --- Вывод известных хостов ---
|
| 276 |
+
peers = storage.get_known_peers(my_id)
|
| 277 |
+
print("[UDP Discovery] Known peers:", [p["id"] for p in peers])
|
| 278 |
+
|
| 279 |
+
msg_dict = {
|
| 280 |
"id": my_id,
|
| 281 |
"name": agent_name,
|
| 282 |
"addresses": local_addresses,
|
| 283 |
"pubkey": my_pubkey
|
| 284 |
+
}
|
| 285 |
|
| 286 |
for port in local_ports:
|
| 287 |
# IPv4 broadcast
|
|
|
|
| 289 |
addrs = netifaces.ifaddresses(iface).get(netifaces.AF_INET, [])
|
| 290 |
for a in addrs:
|
| 291 |
if "broadcast" in a:
|
| 292 |
+
send_discovery_packets(msg_dict, a["broadcast"], port)
|
| 293 |
+
# можно для проверки сразу и 255.255.255.255:
|
| 294 |
+
send_discovery_packets(msg_dict, "255.255.255.255", port)
|
| 295 |
+
|
| 296 |
+
# IPv6 multicast пока выключен для отладки
|
| 297 |
+
# for iface in netifaces.interfaces():
|
| 298 |
+
# ifaddrs = netifaces.ifaddresses(iface).get(netifaces.AF_INET6, [])
|
| 299 |
+
# for a in ifaddrs:
|
| 300 |
+
# ip = a.get("addr")
|
| 301 |
+
# if not ip:
|
| 302 |
+
# continue
|
| 303 |
+
# multicast_addr = "ff02::1"
|
| 304 |
+
# try:
|
| 305 |
+
# if ip.startswith("fe80:"):
|
| 306 |
+
# if_idx = socket.if_nametoindex(iface)
|
| 307 |
+
# multicast_addr = f"ff02::1%{if_idx}"
|
| 308 |
+
# except Exception as e:
|
| 309 |
+
# print(f"[UDP Discovery] IPv6 multicast addr build error on {iface}: {e}")
|
| 310 |
+
# multicast_addr = "ff02::1"
|
| 311 |
+
# send_discovery_packets(msg_dict, multicast_addr, port)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 312 |
|
| 313 |
time.sleep(DISCOVERY_INTERVAL)
|
| 314 |
|