packages/hyprspace: support manually configuring relays
This commit is contained in:
parent
02bee68d13
commit
8f3105cdd3
7 changed files with 229 additions and 9 deletions
|
@ -33,6 +33,7 @@ func init() {
|
||||||
cmd.Register(&Down)
|
cmd.Register(&Down)
|
||||||
cmd.Register(&Status)
|
cmd.Register(&Status)
|
||||||
cmd.Register(&Peers)
|
cmd.Register(&Peers)
|
||||||
|
cmd.Register(&Route)
|
||||||
cmd.Register(&cmd.Version)
|
cmd.Register(&cmd.Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
47
packages/networking/hyprspace/cli/route.go
Normal file
47
packages/networking/hyprspace/cli/route.go
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/DataDrake/cli-ng/v2/cmd"
|
||||||
|
"github.com/hyprspace/hyprspace/rpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Route = cmd.Sub{
|
||||||
|
Name: "route",
|
||||||
|
Alias: "r",
|
||||||
|
Short: "Control routing",
|
||||||
|
Args: &RouteArgs{},
|
||||||
|
Run: RouteRun,
|
||||||
|
}
|
||||||
|
|
||||||
|
type RouteArgs struct {
|
||||||
|
Action string
|
||||||
|
InterfaceName string
|
||||||
|
Args []string `zero:"true"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func RouteRun(r *cmd.Root, c *cmd.Sub) {
|
||||||
|
// Parse Command Args
|
||||||
|
args := c.Args.(*RouteArgs)
|
||||||
|
|
||||||
|
action := rpc.RouteAction(args.Action)
|
||||||
|
rArgs := rpc.RouteArgs{
|
||||||
|
Action: action,
|
||||||
|
Args: args.Args,
|
||||||
|
}
|
||||||
|
reply := rpc.Route(args.InterfaceName, rArgs)
|
||||||
|
for _, r := range reply.Routes {
|
||||||
|
var target string
|
||||||
|
connectStatus := ""
|
||||||
|
if r.IsRelay {
|
||||||
|
target = fmt.Sprintf("%s relay target %s", r.RelayAddr, r.TargetAddr)
|
||||||
|
} else {
|
||||||
|
target = fmt.Sprintf("%s direct", r.TargetAddr)
|
||||||
|
}
|
||||||
|
if r.IsConnected {
|
||||||
|
connectStatus = " connected"
|
||||||
|
}
|
||||||
|
fmt.Printf("%s via %s%s\n", &r.Network, target, connectStatus)
|
||||||
|
}
|
||||||
|
}
|
|
@ -178,12 +178,17 @@ func UpRun(r *cmd.Root, c *cmd.Sub) {
|
||||||
if ip.Equal(dstIP) {
|
if ip.Equal(dstIP) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var dst *config.Peer
|
var dst *peer.ID
|
||||||
|
|
||||||
// Check route table for destination address.
|
// Check route table for destination address.
|
||||||
for _, route := range cfg.Routes {
|
for _, route := range cfg.Routes {
|
||||||
if route.Network.Contains(dstIP) {
|
if route.Network.Contains(dstIP) {
|
||||||
dst = &route.Target
|
reroute, found := p2p.FindReroute(route.Network, false)
|
||||||
|
if found {
|
||||||
|
dst = &reroute.To
|
||||||
|
} else {
|
||||||
|
dst = &route.Target.ID
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -195,9 +200,9 @@ func UpRun(r *cmd.Root, c *cmd.Sub) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendPacket(dst config.Peer, packet []byte, plen int) {
|
func sendPacket(dst peer.ID, packet []byte, plen int) {
|
||||||
// Check if we already have an open connection to the destination peer.
|
// Check if we already have an open connection to the destination peer.
|
||||||
stream, ok := activeStreams[dst.ID]
|
stream, ok := activeStreams[dst]
|
||||||
if ok {
|
if ok {
|
||||||
// Write out the packet's length to the libp2p stream to ensure
|
// Write out the packet's length to the libp2p stream to ensure
|
||||||
// we know the full size of the packet at the other end.
|
// we know the full size of the packet at the other end.
|
||||||
|
@ -214,12 +219,12 @@ func sendPacket(dst config.Peer, packet []byte, plen int) {
|
||||||
// If we encounter an error when writing to a stream we should
|
// If we encounter an error when writing to a stream we should
|
||||||
// close that stream and delete it from the active stream map.
|
// close that stream and delete it from the active stream map.
|
||||||
stream.Close()
|
stream.Close()
|
||||||
delete(activeStreams, dst.ID)
|
delete(activeStreams, dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
stream, err := node.NewStream(ctx, dst.ID, p2p.Protocol)
|
stream, err := node.NewStream(ctx, dst, p2p.Protocol)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("[!] Failed to open stream to " + dst.ID.String())
|
fmt.Println("[!] Failed to open stream to " + dst.String())
|
||||||
go p2p.Rediscover()
|
go p2p.Rediscover()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -239,7 +244,7 @@ func sendPacket(dst config.Peer, packet []byte, plen int) {
|
||||||
|
|
||||||
// If all succeeds when writing the packet to the stream
|
// If all succeeds when writing the packet to the stream
|
||||||
// we should reuse this stream by adding it active streams map.
|
// we should reuse this stream by adding it active streams map.
|
||||||
activeStreams[dst.ID] = stream
|
activeStreams[dst] = stream
|
||||||
}
|
}
|
||||||
|
|
||||||
func signalHandler(ctx context.Context, host host.Host, lockPath string, dht *dht.IpfsDHT) {
|
func signalHandler(ctx context.Context, host host.Host, lockPath string, dht *dht.IpfsDHT) {
|
||||||
|
@ -337,7 +342,7 @@ func streamHandler(stream network.Stream) {
|
||||||
tunDev.Iface.Write(packet[:size])
|
tunDev.Iface.Write(packet[:size])
|
||||||
} else {
|
} else {
|
||||||
// FIXME: should decrease the TTL here
|
// FIXME: should decrease the TTL here
|
||||||
sendPacket(route.Target, packet, int(plen))
|
sendPacket(route.Target.ID, packet, int(plen))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
52
packages/networking/hyprspace/p2p/routing.go
Normal file
52
packages/networking/hyprspace/p2p/routing.go
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
package p2p
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/libp2p/go-libp2p/core/peer"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Reroute struct {
|
||||||
|
Network net.IPNet
|
||||||
|
To peer.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
reroutes []Reroute
|
||||||
|
mut sync.Mutex
|
||||||
|
)
|
||||||
|
|
||||||
|
func findReroute(network net.IPNet, doDelete bool) (int, *Reroute, bool) {
|
||||||
|
for i, r := range reroutes {
|
||||||
|
bits1, _ := r.Network.Mask.Size()
|
||||||
|
bits2, _ := network.Mask.Size()
|
||||||
|
if r.Network.IP.Equal(network.IP) && bits1 == bits2 {
|
||||||
|
if doDelete {
|
||||||
|
reroutes = append(reroutes[:i], reroutes[i+1:]...)
|
||||||
|
}
|
||||||
|
return i, &r, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0, nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindReroute(network net.IPNet, doDelete bool) (*Reroute, bool) {
|
||||||
|
mut.Lock()
|
||||||
|
defer mut.Unlock()
|
||||||
|
_, i, r := findReroute(network, doDelete)
|
||||||
|
return i, r
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddReroute(network net.IPNet, peerID peer.ID) {
|
||||||
|
mut.Lock()
|
||||||
|
defer mut.Unlock()
|
||||||
|
if i, _, found := findReroute(network, false); found {
|
||||||
|
reroutes[i].To = peerID
|
||||||
|
} else {
|
||||||
|
reroutes = append(reroutes, Reroute{
|
||||||
|
Network: network,
|
||||||
|
To: peerID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,3 +31,12 @@ func Peers(ifname string) PeersReply {
|
||||||
}
|
}
|
||||||
return reply
|
return reply
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Route(ifname string, args RouteArgs) RouteReply {
|
||||||
|
client := connect(ifname)
|
||||||
|
var reply RouteReply
|
||||||
|
if err := client.Call("HyprspaceRPC.Route", args, &reply); err != nil {
|
||||||
|
log.Fatal("[!] RPC call failed: ", err)
|
||||||
|
}
|
||||||
|
return reply
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package rpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
|
@ -9,8 +10,10 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/hyprspace/hyprspace/config"
|
"github.com/hyprspace/hyprspace/config"
|
||||||
|
"github.com/hyprspace/hyprspace/p2p"
|
||||||
"github.com/libp2p/go-libp2p/core/host"
|
"github.com/libp2p/go-libp2p/core/host"
|
||||||
"github.com/libp2p/go-libp2p/core/network"
|
"github.com/libp2p/go-libp2p/core/network"
|
||||||
|
"github.com/libp2p/go-libp2p/core/peer"
|
||||||
"github.com/multiformats/go-multiaddr"
|
"github.com/multiformats/go-multiaddr"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -49,6 +52,76 @@ func (hsr *HyprspaceRPC) Status(args *Args, reply *StatusReply) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (hsr *HyprspaceRPC) Route(args *RouteArgs, reply *RouteReply) error {
|
||||||
|
switch args.Action {
|
||||||
|
case Show:
|
||||||
|
var routes []RouteInfo
|
||||||
|
for _, r := range hsr.config.Routes {
|
||||||
|
connected := hsr.host.Network().Connectedness(r.Target.ID) == network.Connected
|
||||||
|
reroute, found := p2p.FindReroute(r.Network, false)
|
||||||
|
relayAddr := r.Target.ID
|
||||||
|
if found {
|
||||||
|
relayAddr = reroute.To
|
||||||
|
}
|
||||||
|
routes = append(routes, RouteInfo{
|
||||||
|
Network: r.Network,
|
||||||
|
TargetAddr: r.Target.ID,
|
||||||
|
RelayAddr: relayAddr,
|
||||||
|
IsRelay: found,
|
||||||
|
IsConnected: connected,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
*reply = RouteReply{
|
||||||
|
Routes: routes,
|
||||||
|
}
|
||||||
|
case Relay:
|
||||||
|
var networks []net.IPNet
|
||||||
|
if args.Args[0] == "all" {
|
||||||
|
for _, r := range hsr.config.Routes {
|
||||||
|
networks = append(networks, r.Network)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_, network, err := net.ParseCIDR(args.Args[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if _, found := config.FindRoute(hsr.config.Routes, *network); !found {
|
||||||
|
return errors.New("no such network")
|
||||||
|
}
|
||||||
|
networks = []net.IPNet{*network}
|
||||||
|
}
|
||||||
|
p, err := peer.Decode(args.Args[1])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if _, found := config.FindPeer(hsr.config.Peers, p); !found {
|
||||||
|
return errors.New("no such peer")
|
||||||
|
}
|
||||||
|
for _, n := range networks {
|
||||||
|
p2p.AddReroute(n, p)
|
||||||
|
}
|
||||||
|
case Reset:
|
||||||
|
var networks []net.IPNet
|
||||||
|
if args.Args[0] == "all" {
|
||||||
|
for _, r := range hsr.config.Routes {
|
||||||
|
networks = append(networks, r.Network)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_, network, err := net.ParseCIDR(args.Args[0])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
} else if _, found := config.FindRoute(hsr.config.Routes, *network); !found {
|
||||||
|
return errors.New("no such network")
|
||||||
|
}
|
||||||
|
networks = []net.IPNet{*network}
|
||||||
|
}
|
||||||
|
for _, n := range networks {
|
||||||
|
p2p.FindReroute(n, true)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return errors.New("no such action")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (hsr *HyprspaceRPC) Peers(args *Args, reply *PeersReply) error {
|
func (hsr *HyprspaceRPC) Peers(args *Args, reply *PeersReply) error {
|
||||||
var peerAddrs []string
|
var peerAddrs []string
|
||||||
for _, c := range hsr.host.Network().Conns() {
|
for _, c := range hsr.host.Network().Conns() {
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
package rpc
|
package rpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/libp2p/go-libp2p/core/peer"
|
||||||
|
)
|
||||||
|
|
||||||
type Args struct {
|
type Args struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,3 +21,30 @@ type StatusReply struct {
|
||||||
type PeersReply struct {
|
type PeersReply struct {
|
||||||
PeerAddrs []string
|
PeerAddrs []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RouteAction string
|
||||||
|
|
||||||
|
const (
|
||||||
|
Show RouteAction = "show"
|
||||||
|
Relay = "relay"
|
||||||
|
Reset = "reset"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RouteInfo struct {
|
||||||
|
Network net.IPNet
|
||||||
|
TargetAddr peer.ID
|
||||||
|
RelayAddr peer.ID
|
||||||
|
IsRelay bool
|
||||||
|
IsConnected bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type RouteArgs struct {
|
||||||
|
Action RouteAction
|
||||||
|
Args []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type RouteReply struct {
|
||||||
|
Out string
|
||||||
|
Routes []RouteInfo
|
||||||
|
Err error
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue