feat: surface node p2p runtime visibility

This commit is contained in:
lpf
2026-03-08 22:53:03 +08:00
parent daaac53f5a
commit 29729d7c70
10 changed files with 168 additions and 24 deletions

View File

@@ -33,25 +33,44 @@ func (r *Router) Dispatch(ctx context.Context, req Request, mode string) (Respon
if r.P2P == nil {
return Response{OK: false, Node: req.Node, Action: req.Action, Error: "p2p transport unavailable"}, nil
}
return r.P2P.Send(ctx, req)
resp, err := r.P2P.Send(ctx, req)
return annotateTransport(resp, "p2p", r.P2P.Name(), ""), err
case "relay":
if r.Relay == nil {
return Response{OK: false, Node: req.Node, Action: req.Action, Error: "relay transport unavailable"}, nil
}
return r.Relay.Send(ctx, req)
resp, err := r.Relay.Send(ctx, req)
return annotateTransport(resp, "relay", r.Relay.Name(), ""), err
default: // auto
if r.P2P != nil {
if resp, err := r.P2P.Send(ctx, req); err == nil && resp.OK {
return resp, nil
return annotateTransport(resp, "auto", r.P2P.Name(), ""), nil
}
}
if r.Relay != nil {
return r.Relay.Send(ctx, req)
resp, err := r.Relay.Send(ctx, req)
return annotateTransport(resp, "auto", r.Relay.Name(), "p2p"), err
}
return Response{}, fmt.Errorf("no transport available")
}
}
func annotateTransport(resp Response, mode, usedTransport, fallbackFrom string) Response {
if resp.Payload == nil {
resp.Payload = map[string]interface{}{}
}
if strings.TrimSpace(mode) != "" {
resp.Payload["dispatch_mode"] = strings.TrimSpace(mode)
}
if strings.TrimSpace(usedTransport) != "" {
resp.Payload["used_transport"] = strings.TrimSpace(usedTransport)
}
if strings.TrimSpace(fallbackFrom) != "" {
resp.Payload["fallback_from"] = strings.TrimSpace(fallbackFrom)
}
return resp
}
// WebsocketP2PTransport uses the persistent node websocket as a request/response tunnel
// while the project evolves toward a true peer data channel.
type WebsocketP2PTransport struct {

View File

@@ -71,6 +71,29 @@ func NewWebRTCTransport(stunServers []string) *WebRTCTransport {
func (t *WebRTCTransport) Name() string { return "p2p-webrtc" }
func (t *WebRTCTransport) Snapshot() map[string]interface{} {
t.mu.Lock()
defer t.mu.Unlock()
nodes := make([]map[string]interface{}, 0, len(t.sessions))
active := 0
for nodeID, session := range t.sessions {
status := "connecting"
if session != nil && session.dc != nil && session.dc.ReadyState() == webrtc.DataChannelStateOpen {
status = "open"
active++
}
nodes = append(nodes, map[string]interface{}{
"node": nodeID,
"status": status,
})
}
return map[string]interface{}{
"transport": "webrtc",
"active_sessions": active,
"nodes": nodes,
}
}
func (t *WebRTCTransport) BindSignaler(nodeID string, sender WireSender) {
nodeID = strings.TrimSpace(nodeID)
if nodeID == "" {