GitHub Action commited on
Commit
ca99925
·
1 Parent(s): 4122434

Sync from GitHub with Git LFS

Browse files
Files changed (1) hide show
  1. 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(2048)
176
- msg = json.loads(data.decode("utf-8"))
 
 
 
 
 
 
 
 
 
 
 
 
 
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(UTC).replace(microsecond=0).isoformat()
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(UTC).replace(microsecond=0).isoformat()
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
- msg_data = json.dumps({
 
 
 
 
235
  "id": my_id,
236
  "name": agent_name,
237
  "addresses": local_addresses,
238
  "pubkey": my_pubkey
239
- }).encode("utf-8")
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
- try:
248
- b_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
249
- b_sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
250
- b_sock.sendto(msg_data, (a["broadcast"], port))
251
- b_sock.close()
252
- except Exception as e:
253
- print(f"[UDP Discovery] IPv4 send error on {iface}:{port} -> {e}")
254
-
255
- # IPv6 multicast ff02::1
256
- for iface in netifaces.interfaces():
257
- ifaddrs = netifaces.ifaddresses(iface).get(netifaces.AF_INET6, [])
258
- for a in ifaddrs:
259
- ip = a.get("addr")
260
- if not ip:
261
- continue
262
- multicast_addr = f"ff02::1%{iface}" if ip.startswith("fe80:") else "ff02::1"
263
- try:
264
- m_sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
265
- m_sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_IF, socket.if_nametoindex(iface))
266
- m_sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, 1)
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