automatic handshake and connect
This commit is contained in:
1 parent
dbc460f0bb
commit
da446f5ab0
7 files changed
+283
-10
No files matched your search
@@ -6,10 +6,9 @@ from typing import Dict, Any
|
||||
|
||||
from base58 import b58decode
|
||||
from sanic import response
|
||||
from sqlalchemy import select
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from app.core.logger import make_log
|
||||
from app.core.models.my_network import KnownNode
|
||||
from app.core.network.constants import CURRENT_PROTOCOL_VERSION, NODE_TYPE_PRIVATE
|
||||
from app.core.network.config import NODE_PRIVACY
|
||||
from app.core.network.handshake import build_handshake_payload, compute_node_info, sign_response
|
||||
@@ -17,6 +16,52 @@ from app.core.network.nodes import upsert_known_node, list_known_public_nodes
|
||||
from app.core.network.semver import compatibility
|
||||
from app.core.network.guard import check_rate_limit, check_timestamp_fresh, check_and_remember_nonce
|
||||
from app.core.network.config import HANDSHAKE_TS_TOLERANCE_SEC
|
||||
from app.core.ipfs_client import swarm_connect
|
||||
|
||||
|
||||
def _port_from_public_host(public_host: str) -> int:
|
||||
"""Return an integer port extracted from a public_host URL or host:port string."""
|
||||
if not public_host:
|
||||
return 80
|
||||
parsed = urlparse(public_host)
|
||||
if parsed.scheme:
|
||||
if parsed.port:
|
||||
return parsed.port
|
||||
return 443 if parsed.scheme == "https" else 80
|
||||
host_port = public_host.strip()
|
||||
if ":" in host_port:
|
||||
candidate = host_port.rsplit(":", 1)[-1]
|
||||
try:
|
||||
return int(candidate)
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
return 80
|
||||
|
||||
|
||||
def _extract_ipfs_meta(payload: Dict[str, Any]) -> Dict[str, Any]:
|
||||
ipfs = payload or {}
|
||||
multiaddrs = ipfs.get("multiaddrs") or []
|
||||
if not isinstance(multiaddrs, list):
|
||||
multiaddrs = [multiaddrs]
|
||||
normalized_multiaddrs = [str(m) for m in multiaddrs if m]
|
||||
meta: Dict[str, Any] = {}
|
||||
if normalized_multiaddrs:
|
||||
meta["multiaddrs"] = normalized_multiaddrs
|
||||
peer_id = ipfs.get("peer_id")
|
||||
if peer_id:
|
||||
meta["peer_id"] = str(peer_id)
|
||||
agent = ipfs.get("agent_version") or ipfs.get("agentVersion")
|
||||
if agent:
|
||||
meta["agent_version"] = str(agent)
|
||||
return meta
|
||||
|
||||
|
||||
async def _connect_ipfs_multiaddrs(addrs):
|
||||
for addr in addrs or []:
|
||||
try:
|
||||
await swarm_connect(addr)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
async def s_api_v1_network_info(request):
|
||||
@@ -61,6 +106,7 @@ async def s_api_v1_network_handshake(request):
|
||||
return response.json({"error": "NONCE_REPLAY"}, status=400)
|
||||
|
||||
peer_version = str(data.get("version"))
|
||||
ipfs_meta = _extract_ipfs_meta(data.get("ipfs") or {})
|
||||
comp = compatibility(peer_version, CURRENT_PROTOCOL_VERSION)
|
||||
if comp == "blocked":
|
||||
# We still store the node but respond with 409
|
||||
@@ -68,7 +114,7 @@ async def s_api_v1_network_handshake(request):
|
||||
await upsert_known_node(
|
||||
request.ctx.db_session,
|
||||
host=data.get("public_host"),
|
||||
port=int(str(data.get("public_host") or "").split(":")[-1]) if ":" in str(data.get("public_host") or "") else 80,
|
||||
port=_port_from_public_host(data.get("public_host")),
|
||||
public_key=str(data.get("public_key")),
|
||||
meta={
|
||||
"version": peer_version,
|
||||
@@ -76,6 +122,7 @@ async def s_api_v1_network_handshake(request):
|
||||
"is_public": data.get("node_type", "public") != "private",
|
||||
"public_host": data.get("public_host"),
|
||||
"unsupported_last_checked_at": datetime.utcnow().isoformat(),
|
||||
"ipfs": ipfs_meta,
|
||||
}
|
||||
)
|
||||
except Exception:
|
||||
@@ -111,7 +158,7 @@ async def s_api_v1_network_handshake(request):
|
||||
await upsert_known_node(
|
||||
request.ctx.db_session,
|
||||
host=data.get("public_host"),
|
||||
port=int(str(data.get("public_host") or "").split(":")[-1]) if ":" in str(data.get("public_host") or "") else 80,
|
||||
port=_port_from_public_host(data.get("public_host")),
|
||||
public_key=str(data.get("public_key")),
|
||||
meta={
|
||||
"version": peer_version,
|
||||
@@ -120,13 +167,16 @@ async def s_api_v1_network_handshake(request):
|
||||
"public_host": data.get("public_host"),
|
||||
"last_metrics": data.get("metrics", {}),
|
||||
"capabilities": data.get("capabilities", {}),
|
||||
"ipfs": ipfs_meta,
|
||||
}
|
||||
)
|
||||
await _connect_ipfs_multiaddrs(ipfs_meta.get("multiaddrs"))
|
||||
except Exception as e:
|
||||
make_log("Handshake", f"Upsert peer failed: {e}", level='warning')
|
||||
|
||||
# Merge advertised peers from the caller (optional field)
|
||||
for n in data.get("known_public_nodes", []) or []:
|
||||
known_ipfs_meta = _extract_ipfs_meta(n.get("ipfs") or {})
|
||||
try:
|
||||
await upsert_known_node(
|
||||
request.ctx.db_session,
|
||||
@@ -139,8 +189,10 @@ async def s_api_v1_network_handshake(request):
|
||||
"is_public": True,
|
||||
"public_host": n.get("public_host") or n.get("host"),
|
||||
"capabilities": n.get("capabilities") or {},
|
||||
"ipfs": known_ipfs_meta,
|
||||
}
|
||||
)
|
||||
await _connect_ipfs_multiaddrs(known_ipfs_meta.get("multiaddrs"))
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
Reference in new issue
Block a user