2024-07-18 17:15:15 +00:00
|
|
|
//go:build p2p
|
|
|
|
// +build p2p
|
|
|
|
|
|
|
|
package p2p
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"net"
|
|
|
|
|
|
|
|
"github.com/mudler/edgevpn/pkg/node"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
|
|
)
|
|
|
|
|
|
|
|
func (f *FederatedServer) Start(ctx context.Context) error {
|
|
|
|
n, err := NewNode(f.p2ptoken)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("creating a new node: %w", err)
|
|
|
|
}
|
|
|
|
err = n.Start(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("creating a new node: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := ServiceDiscoverer(ctx, n, f.p2ptoken, f.service, func(servicesID string, tunnel NodeData) {
|
|
|
|
log.Debug().Msgf("Discovered node: %s", tunnel.ID)
|
2024-08-20 12:45:36 +00:00
|
|
|
}, false); err != nil {
|
2024-07-18 17:15:15 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return f.proxy(ctx, n)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (fs *FederatedServer) proxy(ctx context.Context, node *node.Node) error {
|
|
|
|
|
|
|
|
log.Info().Msgf("Allocating service '%s' on: %s", fs.service, fs.listenAddr)
|
|
|
|
// Open local port for listening
|
|
|
|
l, err := net.Listen("tcp", fs.listenAddr)
|
|
|
|
if err != nil {
|
|
|
|
log.Error().Err(err).Msg("Error listening")
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
// ll.Info("Binding local port on", srcaddr)
|
2024-08-17 06:28:52 +00:00
|
|
|
go func() {
|
|
|
|
<-ctx.Done()
|
|
|
|
l.Close()
|
|
|
|
}()
|
2024-08-20 12:45:36 +00:00
|
|
|
|
|
|
|
nodeAnnounce(ctx, node)
|
2024-07-18 17:15:15 +00:00
|
|
|
|
|
|
|
defer l.Close()
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
return errors.New("context canceled")
|
|
|
|
default:
|
2024-08-13 14:17:18 +00:00
|
|
|
log.Debug().Msgf("New connection from %s", l.Addr().String())
|
2024-07-18 17:15:15 +00:00
|
|
|
// Listen for an incoming connection.
|
|
|
|
conn, err := l.Accept()
|
|
|
|
if err != nil {
|
|
|
|
fmt.Println("Error accepting: ", err.Error())
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle connections in a new goroutine, forwarding to the p2p service
|
|
|
|
go func() {
|
2024-08-20 12:45:36 +00:00
|
|
|
workerID := ""
|
2024-08-13 14:17:18 +00:00
|
|
|
if fs.workerTarget != "" {
|
2024-08-20 12:45:36 +00:00
|
|
|
workerID = fs.workerTarget
|
2024-08-13 14:17:18 +00:00
|
|
|
} else if fs.loadBalanced {
|
|
|
|
log.Debug().Msgf("Load balancing request")
|
2024-07-18 21:18:53 +00:00
|
|
|
|
2024-08-20 12:45:36 +00:00
|
|
|
workerID = fs.SelectLeastUsedServer()
|
|
|
|
if workerID == "" {
|
2024-08-16 17:34:36 +00:00
|
|
|
log.Debug().Msgf("Least used server not found, selecting random")
|
2024-08-20 12:45:36 +00:00
|
|
|
workerID = fs.RandomServer()
|
2024-07-18 21:18:53 +00:00
|
|
|
}
|
|
|
|
} else {
|
2024-08-20 12:45:36 +00:00
|
|
|
workerID = fs.RandomServer()
|
2024-07-18 21:18:53 +00:00
|
|
|
}
|
2024-07-18 17:15:15 +00:00
|
|
|
|
2024-08-20 12:45:36 +00:00
|
|
|
if workerID == "" {
|
2024-08-13 14:17:18 +00:00
|
|
|
log.Error().Msg("No available nodes yet")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-08-20 12:45:36 +00:00
|
|
|
log.Debug().Msgf("Selected node %s", workerID)
|
|
|
|
nodeData, exists := GetNode(fs.service, workerID)
|
|
|
|
if !exists {
|
|
|
|
log.Error().Msgf("Node %s not found", workerID)
|
2024-07-18 17:15:15 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-08-20 12:45:36 +00:00
|
|
|
proxyP2PConnection(ctx, node, nodeData.ServiceID, conn)
|
2024-08-13 14:17:18 +00:00
|
|
|
if fs.loadBalanced {
|
2024-08-20 12:45:36 +00:00
|
|
|
fs.RecordRequest(workerID)
|
2024-08-13 14:17:18 +00:00
|
|
|
}
|
2024-07-18 17:15:15 +00:00
|
|
|
}()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|