Skip to content

Commit

Permalink
Fix discovery server config bugs (#40)
Browse files Browse the repository at this point in the history
* fix discovery server bugs

* fix bug where oneshot couldnt connect to discovery server if using ipv6 based redirect
  • Loading branch information
raphaelreyna authored May 19, 2024
1 parent e1ecff9 commit 68719ca
Show file tree
Hide file tree
Showing 13 changed files with 103 additions and 32 deletions.
8 changes: 6 additions & 2 deletions v2/integration_testing/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"time"

Expand Down Expand Up @@ -144,8 +145,11 @@ func (suite *TestSuite) SetupSuite() {
suite.Require().NoError(err)

newCmdPath := filepath.Join(suite.TestDir, "oneshot.testing")
cpOPut, err := exec.Command("cp", cmdPath, newCmdPath).CombinedOutput()
suite.Require().NoError(err, "failed to copy oneshot binary: %s", string(cpOPut))
if runtime.GOOS == "darwin" {
newCmdPath = filepath.Join(filepath.Dir(suite.TestDir), "oneshot.testing")
}
cpOut, err := exec.Command("cp", cmdPath, newCmdPath).CombinedOutput()
suite.Require().NoError(err, "failed to copy oneshot binary: %s", string(cpOut))

err = os.Chdir(suite.TestDir)
suite.Require().NoError(err)
Expand Down
39 changes: 37 additions & 2 deletions v2/pkg/commands/config/get/cobra.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package get

import (
"fmt"
"os"

"github.com/forestnode-io/oneshot/v2/pkg/configuration"
Expand Down Expand Up @@ -31,7 +32,7 @@ func (c *Cmd) Cobra() *cobra.Command {
Short: "Get an individual value from a oneshot configuration file.",
Long: "Get an individual value from a oneshot configuration file.",
RunE: c.run,
Args: cobra.ExactArgs(1),
Args: cobra.MaximumNArgs(1),
}

c.cobraCommand.SetUsageTemplate(usageTemplate)
Expand All @@ -40,7 +41,41 @@ func (c *Cmd) Cobra() *cobra.Command {
}

func (c *Cmd) run(cmd *cobra.Command, args []string) error {
configData := viper.Get(args[0])
m := map[string]any{}
err := viper.Unmarshal(&m)
if err != nil {
return fmt.Errorf("failed to unmarshal configuration: %w", err)
}

dc, ok := m["discovery"].(map[string]any)
if !ok {
return fmt.Errorf("failed to get discovery configuration")
}

key, ok := dc["key"].(string)
if !ok {
return fmt.Errorf("failed to get discovery key")
}

if key != "" {
if 8 < len(key) {
key = key[:8] + "..."
} else {
key = "********"
}
viper.Set("discovery.key", key)
}
dc["key"] = key
m["discovery"] = dc

v := viper.New()
v.MergeConfigMap(m)

if len(args) == 0 || args[0] == "" {
return yaml.NewEncoder(os.Stdout).Encode(v.AllSettings())
}

configData := v.Get(args[0])
if configData == nil {
return output.UsageErrorF("no such key: %s", args[0])
}
Expand Down
2 changes: 1 addition & 1 deletion v2/pkg/commands/discovery-server/cobra.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func (c *Cmd) run(cmd *cobra.Command, args []string) error {
if err != nil {
return fmt.Errorf("unable to get source ip: %w", err)
}
uaConf.Domain = sip
uaConf.Domain = sip.String()
}
}
if uaConf.Port == 0 {
Expand Down
4 changes: 2 additions & 2 deletions v2/pkg/commands/p2p/client/receive/cobra.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,15 @@ func (c *Cmd) receive(cmd *cobra.Command, args []string) error {

signaller, bat, err = signallers.NewFileClientSignaller(offerFilePath, answerFilePath)
} else {
corr, err := discovery.NegotiateOfferRequest(ctx, dsConfig.Host, baConfig.Username, baConfig.Password, http.DefaultClient)
corr, err := discovery.NegotiateOfferRequest(ctx, dsConfig.Addr, baConfig.Username, baConfig.Password, http.DefaultClient)
if err != nil {
return fmt.Errorf("failed to negotiate offer request: %w", err)
}
transport, err = client.NewTransport(corr.RTCConfiguration)
if err != nil {
return fmt.Errorf("failed to create transport: %w", err)
}
signaller, bat, err = signallers.NewServerClientSignaller(dsConfig.Host, corr.SessionID, corr.RTCSessionDescription, nil)
signaller, bat, err = signallers.NewServerClientSignaller(dsConfig.Addr, corr.SessionID, corr.RTCSessionDescription, nil)
}
if err != nil {
return fmt.Errorf("failed to create signaller: %w", err)
Expand Down
4 changes: 2 additions & 2 deletions v2/pkg/commands/p2p/client/send/cobra.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"strings"
"time"

"github.com/moby/moby/pkg/namesgenerator"
"github.com/forestnode-io/oneshot/v2/pkg/commands/p2p/client/discovery"
"github.com/forestnode-io/oneshot/v2/pkg/commands/p2p/client/send/configuration"
rootconfig "github.com/forestnode-io/oneshot/v2/pkg/configuration"
Expand All @@ -22,6 +21,7 @@ import (
"github.com/forestnode-io/oneshot/v2/pkg/net/webrtc/sdp/signallers"
oneshotos "github.com/forestnode-io/oneshot/v2/pkg/os"
"github.com/forestnode-io/oneshot/v2/pkg/output"
"github.com/moby/moby/pkg/namesgenerator"
"github.com/pion/webrtc/v3"
"github.com/rs/zerolog"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -69,7 +69,7 @@ func (c *Cmd) send(cmd *cobra.Command, args []string) error {

fileName = config.Name
webRTCSignallingDir = p2pConfig.DiscoveryDir
webRTCSignallingURL = dsConfig.Host
webRTCSignallingURL = dsConfig.Addr

err error
)
Expand Down
9 changes: 6 additions & 3 deletions v2/pkg/commands/root/discoveryServer.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func (r *rootCommand) sendArrivalToDiscoveryServer(ctx context.Context, cmd stri
dsConfig = config.Discovery
)

if dsConfig.Host == "" {
if dsConfig.Addr == "" {
return nil
}

Expand All @@ -29,11 +29,14 @@ func (r *rootCommand) sendArrivalToDiscoveryServer(ctx context.Context, cmd stri
Cmd: cmd,
}

ipThatCanReachDiscoveryServer, err := oneshotnet.GetSourceIP(dsConfig.Host, 0)
ipThatCanReachDiscoveryServer, err := oneshotnet.GetSourceIP(dsConfig.Addr, 0)
if err != nil {
return fmt.Errorf("unable to reach the discovery server: %w", err)
}
arrival.Redirect = ipThatCanReachDiscoveryServer
arrival.Redirect = ipThatCanReachDiscoveryServer.String()
if ipThatCanReachDiscoveryServer.To16() != nil {
arrival.Redirect = "[" + arrival.Redirect + "]"
}

scheme := "http"
if config.Server.TLSCert != "" {
Expand Down
2 changes: 1 addition & 1 deletion v2/pkg/commands/root/listenWebRTC.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func getSignaller(ctx context.Context, config *configuration.Root, portMapAddr s
var (
dsConf = config.Discovery
p2pConf = config.NATTraversal.P2P
webRTCSignallingURL = dsConf.Host
webRTCSignallingURL = dsConf.Addr
webRTCSignallingDir = p2pConf.DiscoveryDir
)

Expand Down
22 changes: 20 additions & 2 deletions v2/pkg/commands/root/runServer.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,24 @@ func (r *rootCommand) init(cmd *cobra.Command, args []string) error {
return fmt.Errorf("failed to hydrate configuration: %w", err)
}

if r.config.Discovery.Addr != "" {
host, port, err := net.SplitHostPort(r.config.Discovery.Addr)
if err != nil {
if !strings.Contains(err.Error(), "missing port in address") {
return fmt.Errorf("failed to parse discovery server URL: %w", err)
}
host = r.config.Discovery.Addr
}
if port == "" {
if r.config.Discovery.Insecure {
port = "80"
} else {
port = "443"
}
}
r.config.Discovery.Addr = net.JoinHostPort(host, port)
}

if r.config.Output.Quiet {
output.Quiet(ctx)
} else {
Expand Down Expand Up @@ -140,7 +158,7 @@ func (r *rootCommand) runServer(cmd *cobra.Command, args []string) error {
dsConfig := r.config.Discovery
connConf := signallingserver.DiscoveryServerConfig{
Enabled: dsConfig.Enabled,
URL: dsConfig.Host,
URL: dsConfig.Addr,
Key: dsConfig.Key,
Insecure: dsConfig.Insecure,
SendReports: dsConfig.Reports.Enabled,
Expand All @@ -152,7 +170,7 @@ func (r *rootCommand) runServer(cmd *cobra.Command, args []string) error {
APIVersion: version.APIVersion,
},
}
if err := signallingserver.ConnectToDiscoveryServer(ctx, connConf); err != nil {
if err := signallingserver.ConnectToDiscoveryServer(ctx, &connConf); err != nil {
log.Error().Err(err).
Msg("failed to connect to discovery server")
} else {
Expand Down
2 changes: 1 addition & 1 deletion v2/pkg/configuration/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ func setDefault() {

// discovery
viper.SetDefault("discovery.enabled", true)
viper.SetDefault("discovery.host", "")
viper.SetDefault("discovery.addr", "")
viper.SetDefault("discovery.key", "")
viper.SetDefault("discovery.keypath", "")
viper.SetDefault("discovery.insecure", false)
Expand Down
4 changes: 2 additions & 2 deletions v2/pkg/configuration/discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ type Reports struct {

type Discovery struct {
Enabled bool `mapstructure:"enabled" yaml:"enabled"`
Host string `mapstructure:"host" yaml:"host"`
Addr string `mapstructure:"addr" yaml:"addr"`
Key string `mapstructure:"key" yaml:"key" json:"-"`
KeyPath string `mapstructure:"keyPath" yaml:"keyPath"`
Insecure bool `mapstructure:"insecure" yaml:"insecure"`
Expand All @@ -37,7 +37,7 @@ func setDiscoveryFlags(cmd *cobra.Command) {
defer cmd.PersistentFlags().AddFlagSet(fs)

flags.Bool(fs, "discovery.enabled", "discovery-enabled", "Enable discovery server.")
flags.String(fs, "discovery.url", "discovery-url", "URL of the discovery server to connect to.")
flags.String(fs, "discovery.addr", "discovery-addr", "Address (host:port) of the discovery server to connect to.")
flags.String(fs, "discovery.keypath", "discovery-key-path", "Path to the key to present to the discovery server.")
flags.String(fs, "discovery.key", "discovery-key", "Key to present to the discovery server.")
fs.Lookup("discovery-key").DefValue = ""
Expand Down
14 changes: 10 additions & 4 deletions v2/pkg/file/tar.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func tarball(compress bool, paths []string, w io.Writer) error {
return name
}

walkFunc := func(path string) func(string, os.FileInfo, error) error {
walkFunc := func(path string, buf []byte) func(string, os.FileInfo, error) error {
dir := filepath.Dir(path)
return func(fp string, info os.FileInfo, err error) error {
if err != nil {
Expand Down Expand Up @@ -72,7 +72,7 @@ func tarball(compress bool, paths []string, w io.Writer) error {
}
defer fh.Close()

if _, err = io.Copy(tw, fh); err != nil {
if _, err = io.CopyBuffer(tw, fh, buf); err != nil {
return err
}

Expand All @@ -87,12 +87,18 @@ func tarball(compress bool, paths []string, w io.Writer) error {
return err
}
if info.IsDir() { // Archiving a directory; needs to be walked
err := filepath.Walk(path, walkFunc(path))
buf := make([]byte, 32*1024)
err := filepath.Walk(path, walkFunc(path, buf))
if err != nil {
return err
}
} else { // Archiving a single file or symlink
if err = walkFunc(path)(path, info, nil); err != nil {
size := info.Size()
if size == 0 {
size = 32 * 1024
}
buf := make([]byte, size)
if err = walkFunc(path, buf)(path, info, nil); err != nil {
return err
}
}
Expand Down
10 changes: 5 additions & 5 deletions v2/pkg/net/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"strings"
"time"

"github.com/jackpal/gateway"
"github.com/forestnode-io/oneshot/v2/pkg/log"
"github.com/jackpal/gateway"
)

// HostAddresses returns all available ip addresses from all interfaces
Expand Down Expand Up @@ -45,11 +45,11 @@ func HostAddresses() ([]string, error) {
// GetSourceIP returns the ip address used to access target:port
// If target is the empty string then the default gateway ip is used.
// If the port is 0, then 80 is used by default.
func GetSourceIP(target string, port int) (string, error) {
func GetSourceIP(target string, port int) (net.IP, error) {
if target == "" {
ip, err := gateway.DiscoverGateway()
if err != nil {
return "", err
return nil, err
}
target = ip.String()
}
Expand All @@ -64,13 +64,13 @@ func GetSourceIP(target string, port int) (string, error) {
conn, err = net.Dial("udp", target)
}
if err != nil {
return "", err
return nil, err
}
defer conn.Close()

localAddr := conn.LocalAddr().(*net.UDPAddr)

return localAddr.IP.String(), nil
return localAddr.IP, nil
}

func PreferNonPrivateIP(ips []string) (string, string) {
Expand Down
15 changes: 10 additions & 5 deletions v2/pkg/net/webrtc/signallingserver/discoveryServer.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,32 +70,37 @@ func WithDiscoveryServer(ctx context.Context) (context.Context, <-chan struct{})

// ConnectToDiscoveryServer connects to the discovery server and sends a handshake.
// The connection is kept open and stuffed into the context.
func ConnectToDiscoveryServer(ctx context.Context, c DiscoveryServerConfig) error {
func ConnectToDiscoveryServer(ctx context.Context, c *DiscoveryServerConfig) error {
dds, ok := ctx.Value(discoveryServerKey{}).(**DiscoveryServer)
if !ok || dds == nil {
return nil
}

defer func() {
if (*dds).config == nil {
(*dds).config = c
}
}()

if !c.Enabled {
(*dds).config = &c
return nil
}

ctx = context.WithoutCancel(ctx)
log := zerolog.Ctx(ctx)

log.Debug().Msg("connecting to discovery server")
conn, err := getConnectionToDiscoveryServer(ctx, &c)
conn, err := getConnectionToDiscoveryServer(ctx, c)
if err != nil {
return fmt.Errorf("failed to connect to discovery server: %w", err)
}

log.Debug().Msg("opening bidirectional stream to discovery server")
ds, err := newDiscoveryServer(ctx, &c, conn)
ds, err := newDiscoveryServer(ctx, c, conn)
if err != nil {
return fmt.Errorf("failed to create discovery server: %w", err)
}
ds.config = &c
ds.config = c
ds.doneFunc = (*dds).doneFunc
*dds = ds
return nil
Expand Down

0 comments on commit 68719ca

Please sign in to comment.