Files
clawgo/pkg/nodes/transport.go

67 lines
1.8 KiB
Go

package nodes
import (
"context"
"fmt"
"strings"
)
// Transport abstracts node data-plane delivery.
type Transport interface {
Name() string
Send(ctx context.Context, req Request) (Response, error)
}
// Router prefers p2p transport and falls back to relay.
type Router struct {
P2P Transport
Relay Transport
}
func (r *Router) Dispatch(ctx context.Context, req Request, mode string) (Response, error) {
m := strings.ToLower(strings.TrimSpace(mode))
if m == "" {
m = "auto"
}
switch m {
case "p2p":
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)
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)
default: // auto
if r.P2P != nil {
if resp, err := r.P2P.Send(ctx, req); err == nil && resp.OK {
return resp, nil
}
}
if r.Relay != nil {
return r.Relay.Send(ctx, req)
}
return Response{}, fmt.Errorf("no transport available")
}
}
// StubP2PTransport provides phase-2 negotiation scaffold.
type StubP2PTransport struct{}
func (s *StubP2PTransport) Name() string { return "p2p" }
func (s *StubP2PTransport) Send(ctx context.Context, req Request) (Response, error) {
_ = ctx
return Response{OK: false, Node: req.Node, Action: req.Action, Error: "p2p session not established yet"}, nil
}
// StubRelayTransport provides executable placeholder until real bridge lands.
type StubRelayTransport struct{}
func (s *StubRelayTransport) Name() string { return "relay" }
func (s *StubRelayTransport) Send(ctx context.Context, req Request) (Response, error) {
_ = ctx
return Response{OK: false, Node: req.Node, Action: req.Action, Error: "relay bridge not implemented yet"}, nil
}