diff --git a/cmd/skywire-cli/commands/config/auto.go b/cmd/skywire-cli/commands/config/auto.go index fd6ada13fd..1ddaf4beca 100644 --- a/cmd/skywire-cli/commands/config/auto.go +++ b/cmd/skywire-cli/commands/config/auto.go @@ -1,5 +1,4 @@ -//go:build linux -// +build linux +//go:build exclude // Package cliconfig cmd/skywire-cli/commands/config/auto.go package cliconfig diff --git a/cmd/skywire-cli/commands/mdisc/root.go b/cmd/skywire-cli/commands/mdisc/root.go index b630369df9..4add3a9357 100644 --- a/cmd/skywire-cli/commands/mdisc/root.go +++ b/cmd/skywire-cli/commands/mdisc/root.go @@ -21,6 +21,8 @@ import ( ) var mdAddr string + +// var allEntries bool var masterLogger = logging.NewMasterLogger() var packageLogger = masterLogger.PackageLogger("mdisc:disc") @@ -29,7 +31,8 @@ func init() { entryCmd, availableServersCmd, ) - entryCmd.PersistentFlags().StringVar(&mdAddr, "addr", utilenv.DmsgDiscAddr, "address of DMSG discovery server\n") + entryCmd.PersistentFlags().StringVarP(&mdAddr, "addr", "a", "", "DMSG discovery server address\n"+utilenv.DmsgDiscAddr) + // entryCmd.PersistentFlags().BoolVarP(&allEntries, "entries", "e", "", "get all entries") availableServersCmd.PersistentFlags().StringVar(&mdAddr, "addr", utilenv.DmsgDiscAddr, "address of DMSG discovery server\n") var helpflag bool RootCmd.Flags().BoolVarP(&helpflag, "help", "h", false, "help for "+RootCmd.Use) @@ -45,17 +48,30 @@ var RootCmd = &cobra.Command{ var entryCmd = &cobra.Command{ Use: "entry ", Short: "Fetch an entry", - Args: cobra.MinimumNArgs(1), + // Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) - defer cancel() - pk := internal.ParsePK(cmd.Flags(), "visor-public-key", args[0]) - - masterLogger.SetLevel(logrus.InfoLevel) - - entry, err := disc.NewHTTP(mdAddr, &http.Client{}, packageLogger).Entry(ctx, pk) - internal.Catch(cmd.Flags(), err) - internal.PrintOutput(cmd.Flags(), entry, fmt.Sprintln(entry)) + //print help on no args + if len(args) == 0 { + cmd.Help() //nolint + } else { + if mdAddr == "" { + mdAddr = utilenv.DmsgDiscAddr + } + ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) + defer cancel() + pk := internal.ParsePK(cmd.Flags(), "visor-public-key", args[0]) + + masterLogger.SetLevel(logrus.InfoLevel) + + //TODO: fetch all entries + // if allEntries { + // entries, err := disc.NewHTTP(mdAddr, &http.Client{}, packageLogger).AvailableServers(ctx) + // } + + entry, err := disc.NewHTTP(mdAddr, &http.Client{}, packageLogger).Entry(ctx, pk) + internal.Catch(cmd.Flags(), err) + internal.PrintOutput(cmd.Flags(), entry, fmt.Sprintln(entry)) + } }, } diff --git a/cmd/skywire-cli/commands/proxy/proxy.go b/cmd/skywire-cli/commands/proxy/proxy.go new file mode 100644 index 0000000000..df7b4484f6 --- /dev/null +++ b/cmd/skywire-cli/commands/proxy/proxy.go @@ -0,0 +1,225 @@ +// Package skysocksc cmd/skywire-cli/commands/skysocksc/skysocks.go +package skysocksc + +import ( + "bytes" + "fmt" + "math/rand" + "os" + "strings" + "text/tabwriter" + "time" + + "github.com/spf13/cobra" + + "github.com/skycoin/skywire-utilities/pkg/buildinfo" + clirpc "github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc" + "github.com/skycoin/skywire/cmd/skywire-cli/internal" + "github.com/skycoin/skywire/pkg/app/appserver" + "github.com/skycoin/skywire/pkg/servicedisc" +) + +func init() { + RootCmd.PersistentFlags().StringVar(&clirpc.Addr, "rpc", "localhost:3435", "RPC server address") + RootCmd.AddCommand( + proxyStartCmd, + proxyStopCmd, + proxyStatusCmd, + proxyListCmd, + ) + version := buildinfo.Version() + if version == "unknown" { + version = "" + } + proxyStartCmd.Flags().StringVarP(&pk, "pk", "k", "", "server public key") + proxyListCmd.Flags().StringVarP(&pk, "pk", "k", "", "check proxy service discovery for public key") + proxyListCmd.Flags().IntVarP(&count, "num", "n", 0, "number of results to return") + proxyListCmd.Flags().BoolVarP(&isUnFiltered, "unfilter", "u", false, "provide unfiltered results") + proxyListCmd.Flags().StringVarP(&ver, "ver", "v", version, "filter results by version") + proxyListCmd.Flags().StringVarP(&country, "country", "c", "", "filter results by country") + proxyListCmd.Flags().BoolVarP(&isStats, "stats", "s", false, "return only a count of the results") +} + +var proxyStartCmd = &cobra.Command{ + Use: "start", + Short: "start the proxy client", + // Args: cobra.MinimumNArgs(0), + Run: func(cmd *cobra.Command, args []string) { + //check that a valid public key is provided + err := pubkey.Set(pk) + if err != nil { + if len(args) > 0 { + err := pubkey.Set(args[0]) + if err != nil { + internal.PrintFatalError(cmd.Flags(), err) + } + } else { + internal.PrintFatalError(cmd.Flags(), fmt.Errorf("Invalid or missing public key")) + } + } + //connect to RPC + rpcClient, err := clirpc.Client(cmd.Flags()) + if err != nil { + os.Exit(1) + } + //TODO: implement operational timeout + internal.Catch(cmd.Flags(), rpcClient.StartSkysocksClient(pubkey.String())) + internal.PrintOutput(cmd.Flags(), nil, "Starting.") + startProcess := true + for startProcess { + time.Sleep(time.Second * 1) + internal.PrintOutput(cmd.Flags(), nil, ".") + states, err := rpcClient.Apps() + internal.Catch(cmd.Flags(), err) + + type output struct { + AppError string `json:"app_error,omitempty"` + } + + for _, state := range states { + if state.Name == "skysocks-client" { + if state.Status == appserver.AppStatusRunning { + startProcess = false + internal.PrintOutput(cmd.Flags(), nil, fmt.Sprintln("\nRunning!")) + } + if state.Status == appserver.AppStatusErrored { + startProcess = false + out := output{ + AppError: state.DetailedStatus, + } + internal.PrintOutput(cmd.Flags(), out, fmt.Sprintln("\nError! > "+state.DetailedStatus)) + } + } + } + } + }, +} + +var proxyStopCmd = &cobra.Command{ + Use: "stop", + Short: "stop the proxy client", + Run: func(cmd *cobra.Command, args []string) { + rpcClient, err := clirpc.Client(cmd.Flags()) + if err != nil { + os.Exit(1) + } + internal.Catch(cmd.Flags(), rpcClient.StopSkysocksClient()) + internal.PrintOutput(cmd.Flags(), "OK", fmt.Sprintln("OK")) + }, +} + +var proxyStatusCmd = &cobra.Command{ + Use: "status", + Short: "proxy client(s) status", + Run: func(cmd *cobra.Command, args []string) { + //TODO: check status of multiple clients + rpcClient, err := clirpc.Client(cmd.Flags()) + if err != nil { + os.Exit(1) + } + states, err := rpcClient.Apps() + internal.Catch(cmd.Flags(), err) + + var b bytes.Buffer + w := tabwriter.NewWriter(&b, 0, 0, 5, ' ', tabwriter.TabIndent) + internal.Catch(cmd.Flags(), err) + type appState struct { + Status string `json:"status"` + } + var jsonAppStatus appState + for _, state := range states { + if state.Name == "skysocks-client" { + + status := "stopped" + if state.Status == appserver.AppStatusRunning { + status = "running" + } + if state.Status == appserver.AppStatusErrored { + status = "errored" + } + jsonAppStatus = appState{ + Status: status, + } + _, err = fmt.Fprintf(w, "%s\n", status) + internal.Catch(cmd.Flags(), err) + } + } + internal.Catch(cmd.Flags(), w.Flush()) + internal.PrintOutput(cmd.Flags(), jsonAppStatus, b.String()) + }, +} + +var proxyListCmd = &cobra.Command{ + Use: "list", + Short: "List servers", + Long: "List proxy servers from service discovery\n http://sd.skycoin.com/api/services?type=proxy\n http://sd.skycoin.com/api/services?type=vpn&country=US", + Run: func(cmd *cobra.Command, args []string) { + if pk != "" { + err := pubkey.Set(pk) + if err != nil { + internal.PrintFatalError(cmd.Flags(), fmt.Errorf("Invalid or missing public key")) + } + } + rpcClient, err := clirpc.Client(cmd.Flags()) + if err != nil { + internal.PrintFatalRPCError(cmd.Flags(), err) + } + if isUnFiltered { + ver = "" + country = "" + } + servers, err := rpcClient.ProxyServers(ver, country) + if err != nil { + internal.PrintFatalRPCError(cmd.Flags(), err) + } + if len(servers) == 0 { + internal.PrintFatalError(cmd.Flags(), fmt.Errorf("No Servers found")) + } + if isStats { + internal.PrintOutput(cmd.Flags(), fmt.Sprintf("%d Servers\n", len(servers)), fmt.Sprintf("%d Servers\n", len(servers))) + } else { + var msg string + var results []string + limit := len(servers) + if count > 0 && count < limit { + limit = count + } + if pk != "" { + for _, server := range servers { + if strings.Replace(server.Addr.String(), ":44", "", 1) == pk { + results = append(results, server.Addr.String()) + } + } + } else { + for _, server := range servers { + results = append(results, server.Addr.String()) + } + } + rand.Shuffle(len(results), func(i, j int) { + results[i], results[j] = results[j], results[i] + }) + for i := 0; i < limit && i < len(results); i++ { + msg += strings.Replace(results[i], ":44", "", 1) + if server := findServerByPK(servers, results[i]); server != nil && server.Geo != nil { + if server.Geo.Country != "" { + msg += fmt.Sprintf(" | %s\n", server.Geo.Country) + } else { + msg += "\n" + } + } else { + msg += "\n" + } + } + internal.PrintOutput(cmd.Flags(), servers, msg) + } + }, +} + +func findServerByPK(servers []servicedisc.Service, addr string) *servicedisc.Service { + for _, server := range servers { + if server.Addr.String() == addr { + return &server + } + } + return nil +} diff --git a/cmd/skywire-cli/commands/proxy/root.go b/cmd/skywire-cli/commands/proxy/root.go new file mode 100644 index 0000000000..ed11f18c48 --- /dev/null +++ b/cmd/skywire-cli/commands/proxy/root.go @@ -0,0 +1,24 @@ +// Package skysocksc root.go +package skysocksc + +import ( + "github.com/spf13/cobra" + + "github.com/skycoin/skywire-utilities/pkg/cipher" +) + +var ( + isUnFiltered bool + ver string + country string + isStats bool + pubkey cipher.PubKey + pk string + count int +) + +// RootCmd contains commands that interact with the skywire-visor +var RootCmd = &cobra.Command{ + Use: "proxy", + Short: "Skysocks client", +} diff --git a/cmd/skywire-cli/commands/root.go b/cmd/skywire-cli/commands/root.go index 57dd9328f8..716ca4ff61 100644 --- a/cmd/skywire-cli/commands/root.go +++ b/cmd/skywire-cli/commands/root.go @@ -18,12 +18,13 @@ import ( clidmsgpty "github.com/skycoin/skywire/cmd/skywire-cli/commands/dmsgpty" clilog "github.com/skycoin/skywire/cmd/skywire-cli/commands/log" climdisc "github.com/skycoin/skywire/cmd/skywire-cli/commands/mdisc" + cliskysocksc "github.com/skycoin/skywire/cmd/skywire-cli/commands/proxy" clireward "github.com/skycoin/skywire/cmd/skywire-cli/commands/reward" clirtfind "github.com/skycoin/skywire/cmd/skywire-cli/commands/rtfind" cliskyfwd "github.com/skycoin/skywire/cmd/skywire-cli/commands/skyfwd" cliskyrev "github.com/skycoin/skywire/cmd/skywire-cli/commands/skyrev" - cliskysocksc "github.com/skycoin/skywire/cmd/skywire-cli/commands/skysocksc" clisurvey "github.com/skycoin/skywire/cmd/skywire-cli/commands/survey" + cliut "github.com/skycoin/skywire/cmd/skywire-cli/commands/ut" clivisor "github.com/skycoin/skywire/cmd/skywire-cli/commands/visor" clivpn "github.com/skycoin/skywire/cmd/skywire-cli/commands/vpn" "github.com/skycoin/skywire/cmd/skywire-cli/internal" @@ -181,6 +182,7 @@ func init() { clidmsgpty.RootCmd, clivisor.RootCmd, clivpn.RootCmd, + cliut.RootCmd, cliskyfwd.RootCmd, cliskyrev.RootCmd, clireward.RootCmd, diff --git a/cmd/skywire-cli/commands/rtfind/root.go b/cmd/skywire-cli/commands/rtfind/root.go index c0418e4377..86873eaca2 100644 --- a/cmd/skywire-cli/commands/rtfind/root.go +++ b/cmd/skywire-cli/commands/rtfind/root.go @@ -4,6 +4,7 @@ package clirtfind import ( "fmt" "net/http" + "os" "time" "github.com/spf13/cobra" @@ -11,21 +12,25 @@ import ( "github.com/skycoin/skywire-utilities/pkg/cipher" utilenv "github.com/skycoin/skywire-utilities/pkg/skyenv" + clirpc "github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc" "github.com/skycoin/skywire/cmd/skywire-cli/internal" "github.com/skycoin/skywire/pkg/routefinder/rfclient" "github.com/skycoin/skywire/pkg/routing" + "github.com/skycoin/skywire/pkg/skyenv" + "github.com/skycoin/skywire/pkg/visor/visorconfig" ) var frAddr string var frMinHops, frMaxHops uint16 var timeout time.Duration +var skywireconfig string func init() { RootCmd.Flags().SortFlags = false - RootCmd.Flags().Uint16VarP(&frMinHops, "min-hops", "n", 1, "minimum hops") - RootCmd.Flags().Uint16VarP(&frMaxHops, "max-hops", "x", 1000, "maximum hops") + RootCmd.Flags().Uint16VarP(&frMinHops, "min", "n", 1, "minimum hops") + RootCmd.Flags().Uint16VarP(&frMaxHops, "max", "x", 1000, "maximum hops") RootCmd.Flags().DurationVarP(&timeout, "timeout", "t", 10*time.Second, "request timeout") - RootCmd.Flags().StringVarP(&frAddr, "addr", "a", utilenv.RouteFinderAddr, "route finder service address\n") + RootCmd.Flags().StringVarP(&frAddr, "addr", "a", "", "route finder service address\n"+utilenv.RouteFinderAddr) var helpflag bool RootCmd.Flags().BoolVarP(&helpflag, "help", "h", false, "help for "+RootCmd.Use) RootCmd.Flags().MarkHidden("help") //nolint @@ -33,13 +38,56 @@ func init() { // RootCmd is the command that queries the route finder. var RootCmd = &cobra.Command{ - Use: "rtfind ", + Use: "rtfind | ", Short: "Query the Route Finder", - Args: cobra.MinimumNArgs(2), + Long: `Query the Route Finder +Assumes the local visor public key as an argument if only one argument is given`, + // Args: cobra.MinimumNArgs(2), Run: func(cmd *cobra.Command, args []string) { - rfc := rfclient.NewHTTP(frAddr, timeout, &http.Client{}, nil) - var srcPK, dstPK cipher.PubKey + var pk string + //print the help menu if no arguments + if len(args) == 0 { + cmd.Help() //nolint + os.Exit(0) + } + //set the routefinder address. It's not used as the default value to fix the display of the help command + if frAddr == "" { + frAddr = utilenv.RouteFinderAddr + } + //assume the local public key as the first argument if only 1 argument is given ; resize args array to 2 and move the first argument to the second one + if len(args) == 1 { + rpcClient, err := clirpc.Client(cmd.Flags()) + if err == nil { + overview, err := rpcClient.Overview() + if err == nil { + pk = overview.PubKey.String() + } + } + if err != nil { + //visor is not running, try to get pk from config + _, err := os.Stat(skyenv.SkywirePath + "/" + skyenv.ConfigJSON) + if err == nil { + //default to using the package config + skywireconfig = skyenv.SkywirePath + "/" + skyenv.ConfigJSON + } else { + //check for default config in current dir + _, err := os.Stat(skyenv.ConfigName) + if err == nil { + //use skywire-config.json in current dir + skywireconfig = skyenv.ConfigName + } + } + conf, err := visorconfig.ReadFile(skywireconfig) + if err != nil { + internal.PrintFatalError(cmd.Flags(), fmt.Errorf("Failed to read config: %v", err)) + } + pk = conf.PK.Hex() + } + args = append(args[:1], args[0:]...) + copy(args, []string{pk}) + } + rfc := rfclient.NewHTTP(frAddr, timeout, &http.Client{}, nil) internal.Catch(cmd.Flags(), srcPK.Set(args[0])) internal.Catch(cmd.Flags(), dstPK.Set(args[1])) forward := [2]cipher.PubKey{srcPK, dstPK} @@ -48,7 +96,6 @@ var RootCmd = &cobra.Command{ routes, err := rfc.FindRoutes(ctx, []routing.PathEdges{forward, backward}, &rfclient.RouteOptions{MinHops: frMinHops, MaxHops: frMaxHops}) internal.Catch(cmd.Flags(), err) - output := fmt.Sprintf("forward: %v\n reverse: %v", routes[forward][0], routes[backward][0]) outputJSON := struct { Forward []routing.Hop `json:"forward"` diff --git a/cmd/skywire-cli/commands/skysocksc/root.go b/cmd/skywire-cli/commands/skysocksc/root.go deleted file mode 100644 index ecdb76e73d..0000000000 --- a/cmd/skywire-cli/commands/skysocksc/root.go +++ /dev/null @@ -1,12 +0,0 @@ -// Package skysocksc root.go -package skysocksc - -import ( - "github.com/spf13/cobra" -) - -// RootCmd contains commands that interact with the skywire-visor -var RootCmd = &cobra.Command{ - Use: "skysocksc", - Short: "controls for Skysocks client", -} diff --git a/cmd/skywire-cli/commands/skysocksc/skysocksc.go b/cmd/skywire-cli/commands/skysocksc/skysocksc.go deleted file mode 100644 index 5a35d034f3..0000000000 --- a/cmd/skywire-cli/commands/skysocksc/skysocksc.go +++ /dev/null @@ -1,122 +0,0 @@ -// Package skysocksc cmd/skywire-cli/commands/skysocksc/skysocks.go -package skysocksc - -import ( - "bytes" - "fmt" - "os" - "text/tabwriter" - "time" - - "github.com/spf13/cobra" - - clirpc "github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc" - "github.com/skycoin/skywire/cmd/skywire-cli/internal" - "github.com/skycoin/skywire/pkg/app/appserver" -) - -var pk string - -func init() { - RootCmd.PersistentFlags().StringVar(&clirpc.Addr, "rpc", "localhost:3435", "RPC server address") - RootCmd.AddCommand( - skysockscStartCmd, - skysockscStopCmd, - skysockscStatusCmd, - ) - skysockscStartCmd.Flags().StringVar(&pk, "pk", "", "skysocks server public key") -} - -var skysockscStartCmd = &cobra.Command{ - Use: "start", - Short: "start the skysocks-client", - Args: cobra.MinimumNArgs(0), - Run: func(cmd *cobra.Command, args []string) { - rpcClient, err := clirpc.Client(cmd.Flags()) - if err != nil { - os.Exit(1) - } - internal.Catch(cmd.Flags(), rpcClient.StartSkysocksClient(pk)) - internal.PrintOutput(cmd.Flags(), nil, "Starting.") - startProcess := true - for startProcess { - time.Sleep(time.Second * 1) - internal.PrintOutput(cmd.Flags(), nil, ".") - states, err := rpcClient.Apps() - internal.Catch(cmd.Flags(), err) - - type output struct { - AppError string `json:"app_error,omitempty"` - } - - for _, state := range states { - if state.Name == "skysocks-client" { - if state.Status == appserver.AppStatusRunning { - startProcess = false - internal.PrintOutput(cmd.Flags(), nil, fmt.Sprintln("\nRunning!")) - } - if state.Status == appserver.AppStatusErrored { - startProcess = false - out := output{ - AppError: state.DetailedStatus, - } - internal.PrintOutput(cmd.Flags(), out, fmt.Sprintln("\nError! > "+state.DetailedStatus)) - } - } - } - } - }, -} - -var skysockscStopCmd = &cobra.Command{ - Use: "stop", - Short: "stop the skysocks-client", - Run: func(cmd *cobra.Command, _ []string) { - rpcClient, err := clirpc.Client(cmd.Flags()) - if err != nil { - os.Exit(1) - } - internal.Catch(cmd.Flags(), rpcClient.StopSkysocksClient()) - internal.PrintOutput(cmd.Flags(), "OK", fmt.Sprintln("OK")) - }, -} - -var skysockscStatusCmd = &cobra.Command{ - Use: "status", - Short: "skysocks-client status", - Run: func(cmd *cobra.Command, _ []string) { - rpcClient, err := clirpc.Client(cmd.Flags()) - if err != nil { - os.Exit(1) - } - states, err := rpcClient.Apps() - internal.Catch(cmd.Flags(), err) - - var b bytes.Buffer - w := tabwriter.NewWriter(&b, 0, 0, 5, ' ', tabwriter.TabIndent) - internal.Catch(cmd.Flags(), err) - type appState struct { - Status string `json:"status"` - } - var jsonAppStatus appState - for _, state := range states { - if state.Name == "skysocks-client" { - - status := "stopped" - if state.Status == appserver.AppStatusRunning { - status = "running" - } - if state.Status == appserver.AppStatusErrored { - status = "errored" - } - jsonAppStatus = appState{ - Status: status, - } - _, err = fmt.Fprintf(w, "%s\n", status) - internal.Catch(cmd.Flags(), err) - } - } - internal.Catch(cmd.Flags(), w.Flush()) - internal.PrintOutput(cmd.Flags(), jsonAppStatus, b.String()) - }, -} diff --git a/cmd/skywire-cli/commands/ut/root.go b/cmd/skywire-cli/commands/ut/root.go new file mode 100644 index 0000000000..c6586c3898 --- /dev/null +++ b/cmd/skywire-cli/commands/ut/root.go @@ -0,0 +1,133 @@ +// Package cliut cmd/skywire-cli/ut/root.go +package cliut + +import ( + "encoding/json" + "fmt" + "io" + "log" + "net/http" + "os" + "strconv" + "time" + + "github.com/spf13/cobra" + + "github.com/skycoin/skywire-utilities/pkg/cipher" + "github.com/skycoin/skywire/cmd/skywire-cli/internal" +) + +var ( + pubkey cipher.PubKey + pk string + thisPk string + online bool + isStats bool + url string +) + +var minUT int + +func init() { + RootCmd.Flags().StringVarP(&pk, "pk", "k", "", "check uptime for the specified key") + RootCmd.Flags().BoolVarP(&online, "on", "o", false, "list currently online visors") + RootCmd.Flags().BoolVarP(&isStats, "stats", "s", false, "count the number of results") + RootCmd.Flags().IntVarP(&minUT, "min", "n", 75, "list visors meeting minimum uptime") + RootCmd.Flags().StringVarP(&url, "url", "u", "", "specify alternative uptime tracker url\ndefault: http://ut.skywire.skycoin.com/uptimes?v=v2") +} + +// RootCmd contains commands that interact with the skywire-visor +var RootCmd = &cobra.Command{ + Use: "ut", + Short: "query uptime tracker", + Long: "query uptime tracker\n Check local visor daily uptime percent with:\n skywire-cli ut -k $(skywire-cli visor pk)", + Run: func(cmd *cobra.Command, _ []string) { + if url == "" { + url = "http://ut.skywire.skycoin.com/uptimes?v=v2" + } + now := time.Now() + if pk != "" { + err := pubkey.Set(pk) + if err != nil { + internal.PrintFatalError(cmd.Flags(), fmt.Errorf("Invalid or missing public key")) + } else { + url += "&visors=" + pubkey.String() + } + } + utClient := http.Client{ + Timeout: time.Second * 15, // Timeout after 15 seconds + } + + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + log.Fatal(err) + } + + res, getErr := utClient.Do(req) + if getErr != nil { + log.Fatal(getErr) + } + + if res.Body != nil { + defer res.Body.Close() //nolint: errcheck + } + + body, readErr := io.ReadAll(res.Body) + if readErr != nil { + log.Fatal(readErr) + } + + startDate := time.Date(now.Year(), now.Month(), -1, 0, 0, 0, 0, now.Location()).Format("2006-01-02") + endDate := time.Date(now.Year(), now.Month()+1, 1, 0, 0, 0, 0, now.Location()).Add(-1 * time.Second).Format("2006-01-02") + uts := uptimes{} + jsonErr := json.Unmarshal(body, &uts) + if jsonErr != nil { + log.Fatal(jsonErr) + } + var msg []string + for _, j := range uts { + thisPk = j.Pk + if online { + if j.On { + msg = append(msg, fmt.Sprintf(thisPk+"\n")) + } + } else { + selectedDaily(j.Daily, startDate, endDate) + } + } + if online { + if isStats { + internal.PrintOutput(cmd.Flags(), fmt.Sprintf("%d visors online\n", len(msg)), fmt.Sprintf("%d visors online\n", len(msg))) + os.Exit(0) + } + for _, i := range msg { + internal.PrintOutput(cmd.Flags(), i, i) + } + } + }, +} + +func selectedDaily(data map[string]string, startDate, endDate string) { + for date, uptime := range data { + if date >= startDate && date <= endDate { + utfloat, err := strconv.ParseFloat(uptime, 64) + if err != nil { + log.Fatal(err) + } + if utfloat >= float64(minUT) { + fmt.Print(thisPk) + fmt.Print(" ") + fmt.Println(date, uptime) + } + } + } +} + +type uptimes []struct { + Pk string `json:"pk"` + Up int `json:"up"` + Down int `json:"down"` + Pct float64 `json:"pct"` + On bool `json:"on"` + Daily map[string]string `json:"daily,omitempty"` +} diff --git a/cmd/skywire-cli/commands/visor/transports.go b/cmd/skywire-cli/commands/visor/transports.go index 5d1a37c30a..b1b25a9ae3 100644 --- a/cmd/skywire-cli/commands/visor/transports.go +++ b/cmd/skywire-cli/commands/visor/transports.go @@ -53,7 +53,9 @@ var tpCmd = &cobra.Command{ Each Transport is represented as a unique 16 byte (128 bit) UUID value called the Transport ID and has a Transport Type that identifies - a specific implementation of the Transport.`, + a specific implementation of the Transport. + + Types: stcp stcpr sudph dmsg`, } var lsTypesCmd = &cobra.Command{ diff --git a/cmd/skywire-cli/commands/vpn/root.go b/cmd/skywire-cli/commands/vpn/root.go index 1e1c576952..85dd497bc7 100644 --- a/cmd/skywire-cli/commands/vpn/root.go +++ b/cmd/skywire-cli/commands/vpn/root.go @@ -3,6 +3,9 @@ package clivpn import ( "github.com/spf13/cobra" + + "github.com/skycoin/skywire-utilities/pkg/cipher" + clirpc "github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc" ) var ( @@ -12,10 +15,17 @@ var ( ver string country string isStats bool + pubkey cipher.PubKey + pk string + count int ) +func init() { + RootCmd.PersistentFlags().StringVar(&clirpc.Addr, "rpc", "localhost:3435", "RPC server address") +} + // RootCmd contains commands that interact with the skywire-visor var RootCmd = &cobra.Command{ Use: "vpn", - Short: "controls for VPN client", + Short: "VPN client", } diff --git a/cmd/skywire-cli/commands/vpn/vvpn.go b/cmd/skywire-cli/commands/vpn/vvpn.go index 7bd0fb787e..dd9012dc9b 100644 --- a/cmd/skywire-cli/commands/vpn/vvpn.go +++ b/cmd/skywire-cli/commands/vpn/vvpn.go @@ -4,119 +4,52 @@ package clivpn import ( "bytes" "fmt" + "math/rand" "os" "strings" "text/tabwriter" "time" "github.com/spf13/cobra" - "github.com/toqueteos/webbrowser" "github.com/skycoin/skywire-utilities/pkg/buildinfo" - "github.com/skycoin/skywire-utilities/pkg/cipher" clirpc "github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc" - clivisor "github.com/skycoin/skywire/cmd/skywire-cli/commands/visor" "github.com/skycoin/skywire/cmd/skywire-cli/internal" "github.com/skycoin/skywire/pkg/app/appserver" + "github.com/skycoin/skywire/pkg/servicedisc" "github.com/skycoin/skywire/pkg/visor" - "github.com/skycoin/skywire/pkg/visor/visorconfig" ) func init() { - RootCmd.PersistentFlags().StringVar(&clirpc.Addr, "rpc", "localhost:3435", "RPC server address") RootCmd.AddCommand( - vpnListCmd, - vpnUICmd, - vpnURLCmd, vpnStartCmd, vpnStopCmd, vpnStatusCmd, + vpnListCmd, ) version := buildinfo.Version() if version == "unknown" { version = "" } - vpnUICmd.Flags().BoolVarP(&isPkg, "pkg", "p", false, "use package config path") - vpnUICmd.Flags().StringVarP(&path, "config", "c", "", "config path") - vpnURLCmd.Flags().BoolVarP(&isPkg, "pkg", "p", false, "use package config path") - vpnURLCmd.Flags().StringVarP(&path, "config", "c", "", "config path") - vpnListCmd.Flags().BoolVarP(&isUnFiltered, "nofilter", "n", false, "provide unfiltered results") + vpnStartCmd.Flags().StringVarP(&pk, "pk", "k", "", "server public key") + vpnListCmd.Flags().StringVarP(&pk, "pk", "k", "", "check proxy service discovery for public key") + vpnListCmd.Flags().IntVarP(&count, "num", "n", 0, "number of results to return") + vpnListCmd.Flags().BoolVarP(&isUnFiltered, "unfilter", "u", false, "provide unfiltered results") vpnListCmd.Flags().StringVarP(&ver, "ver", "v", version, "filter results by version") vpnListCmd.Flags().StringVarP(&country, "country", "c", "", "filter results by country") vpnListCmd.Flags().BoolVarP(&isStats, "stats", "s", false, "return only a count of the results") } -var vpnUICmd = &cobra.Command{ - Use: "ui", - Short: "Open VPN UI in default browser", - Run: func(cmd *cobra.Command, _ []string) { - var url string - if isPkg { - path = visorconfig.SkywireConfig() - } - if path != "" { - conf, err := visorconfig.ReadFile(path) - if err != nil { - internal.PrintFatalError(cmd.Flags(), fmt.Errorf("Failed to read in config: %v", err)) - } - url = fmt.Sprintf("http://127.0.0.1%s/#/vpn/%s/", clivisor.HypervisorPort(cmd.Flags()), conf.PK.Hex()) - } else { - rpcClient, err := clirpc.Client(cmd.Flags()) - if err != nil { - os.Exit(1) - } - overview, err := rpcClient.Overview() - if err != nil { - internal.PrintFatalError(cmd.Flags(), fmt.Errorf("Failed to connect; is skywire running?: %v", err)) - } - url = fmt.Sprintf("http://127.0.0.1%s/#/vpn/%s/", clivisor.HypervisorPort(cmd.Flags()), overview.PubKey.Hex()) - } - if err := webbrowser.Open(url); err != nil { - internal.PrintFatalError(cmd.Flags(), fmt.Errorf("Failed to open VPN UI in browser:: %v", err)) - } - }, -} - -var vpnURLCmd = &cobra.Command{ - Use: "url", - Short: "Show VPN UI URL", - Run: func(cmd *cobra.Command, _ []string) { - var url string - if isPkg { - path = visorconfig.SkywireConfig() - } - if path != "" { - conf, err := visorconfig.ReadFile(path) - if err != nil { - internal.PrintFatalError(cmd.Flags(), fmt.Errorf("Failed to read in config: %v", err)) - } - url = fmt.Sprintf("http://127.0.0.1%s/#/vpn/%s/", clivisor.HypervisorPort(cmd.Flags()), conf.PK.Hex()) - } else { - rpcClient, err := clirpc.Client(cmd.Flags()) - if err != nil { - os.Exit(1) - } - overview, err := rpcClient.Overview() +var vpnListCmd = &cobra.Command{ + Use: "list", + Short: "List servers", + Run: func(cmd *cobra.Command, args []string) { + if pk != "" { + err := pubkey.Set(pk) if err != nil { - internal.PrintFatalRPCError(cmd.Flags(), err) + internal.PrintFatalError(cmd.Flags(), fmt.Errorf("Invalid or missing public key")) } - url = fmt.Sprintf("http://127.0.0.1%s/#/vpn/%s/", clivisor.HypervisorPort(cmd.Flags()), overview.PubKey.Hex()) - } - - output := struct { - URL string `json:"url"` - }{ - URL: url, } - - internal.PrintOutput(cmd.Flags(), output, fmt.Sprintln(url)) - }, -} - -var vpnListCmd = &cobra.Command{ - Use: "list", - Short: "List public VPN servers", - Run: func(cmd *cobra.Command, _ []string) { rpcClient, err := clirpc.Client(cmd.Flags()) if err != nil { internal.PrintFatalRPCError(cmd.Flags(), err) @@ -130,39 +63,81 @@ var vpnListCmd = &cobra.Command{ internal.PrintFatalRPCError(cmd.Flags(), err) } if len(servers) == 0 { - internal.PrintFatalError(cmd.Flags(), fmt.Errorf("No VPN Servers found")) + internal.PrintFatalError(cmd.Flags(), fmt.Errorf("No Servers found")) } if isStats { - internal.PrintFatalError(cmd.Flags(), fmt.Errorf("%d VPN Servers", len(servers))) - } - - var msg string - for _, i := range servers { - msg += strings.Replace(i.Addr.String(), ":44", "", 1) - if i.Geo != nil { - msg += fmt.Sprintf(" | %s\n", i.Geo.Country) + internal.PrintOutput(cmd.Flags(), fmt.Sprintf("%d Servers\n", len(servers)), fmt.Sprintf("%d Servers\n", len(servers))) + } else { + var msg string + var results []string + limit := len(servers) + if count > 0 && count < limit { + limit = count + } + if pk != "" { + for _, server := range servers { + if strings.Replace(server.Addr.String(), ":3", "", 1) == pk { + results = append(results, server.Addr.String()) + } + } } else { - msg += "\n" + for _, server := range servers { + results = append(results, server.Addr.String()) + } } + rand.Shuffle(len(results), func(i, j int) { + results[i], results[j] = results[j], results[i] + }) + for i := 0; i < limit && i < len(results); i++ { + msg += strings.Replace(results[i], ":3", "", 1) + if server := findServerByPK(servers, results[i]); server != nil && server.Geo != nil { + if server.Geo.Country != "" { + msg += fmt.Sprintf(" | %s\n", server.Geo.Country) + } else { + msg += "\n" + } + } else { + msg += "\n" + } + } + internal.PrintOutput(cmd.Flags(), servers, msg) } - - internal.PrintOutput(cmd.Flags(), servers, msg) }, } +func findServerByPK(servers []servicedisc.Service, addr string) *servicedisc.Service { + for _, server := range servers { + if server.Addr.String() == addr { + return &server + } + } + return nil +} + var vpnStartCmd = &cobra.Command{ Use: "start ", Short: "start the vpn for ", - Args: cobra.MinimumNArgs(1), + // Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { - - var pk cipher.PubKey - internal.Catch(cmd.Flags(), pk.Set(args[0])) + //check that a valid public key is provided + err := pubkey.Set(pk) + if err != nil { + if len(args) > 0 { + err := pubkey.Set(args[0]) + if err != nil { + internal.PrintFatalError(cmd.Flags(), err) + } + } else { + internal.PrintFatalError(cmd.Flags(), fmt.Errorf("Invalid or missing public key")) + } + } + //connect to RPC + internal.Catch(cmd.Flags(), pubkey.Set(args[0])) rpcClient, err := clirpc.Client(cmd.Flags()) if err != nil { os.Exit(1) } - internal.Catch(cmd.Flags(), rpcClient.StartVPNClient(pk)) + internal.Catch(cmd.Flags(), rpcClient.StartVPNClient(pubkey)) internal.PrintOutput(cmd.Flags(), nil, "Starting.") startProcess := true for startProcess { diff --git a/cmd/skywire-cli/commands/vpn/vvpnui.go b/cmd/skywire-cli/commands/vpn/vvpnui.go new file mode 100644 index 0000000000..bc26f794a5 --- /dev/null +++ b/cmd/skywire-cli/commands/vpn/vvpnui.go @@ -0,0 +1,98 @@ +// Package clivpn cmd/skywire-cli/commands/vpn/vvpn.go +package clivpn + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" + "github.com/toqueteos/webbrowser" + + "github.com/skycoin/skywire-utilities/pkg/buildinfo" + clirpc "github.com/skycoin/skywire/cmd/skywire-cli/commands/rpc" + clivisor "github.com/skycoin/skywire/cmd/skywire-cli/commands/visor" + "github.com/skycoin/skywire/cmd/skywire-cli/internal" + "github.com/skycoin/skywire/pkg/visor/visorconfig" +) + +func init() { + RootCmd.AddCommand( + vpnUICmd, + vpnURLCmd, + ) + version := buildinfo.Version() + if version == "unknown" { + version = "" //nolint + } + vpnUICmd.Flags().BoolVarP(&isPkg, "pkg", "p", false, "use package config path: "+visorconfig.SkywirePath) + vpnUICmd.Flags().StringVarP(&path, "config", "c", "", "config path") + vpnURLCmd.Flags().BoolVarP(&isPkg, "pkg", "p", false, "use package config path: "+visorconfig.SkywirePath) + vpnURLCmd.Flags().StringVarP(&path, "config", "c", "", "config path") +} + +var vpnUICmd = &cobra.Command{ + Use: "ui", + Short: "Open VPN UI in default browser", + Run: func(cmd *cobra.Command, _ []string) { + var url string + if isPkg { + path = visorconfig.SkywireConfig() + } + if path != "" { + conf, err := visorconfig.ReadFile(path) + if err != nil { + internal.PrintFatalError(cmd.Flags(), fmt.Errorf("Failed to read in config: %v", err)) + } + url = fmt.Sprintf("http://127.0.0.1%s/#/vpn/%s/", clivisor.HypervisorPort(cmd.Flags()), conf.PK.Hex()) + } else { + rpcClient, err := clirpc.Client(cmd.Flags()) + if err != nil { + os.Exit(1) + } + overview, err := rpcClient.Overview() + if err != nil { + internal.PrintFatalError(cmd.Flags(), fmt.Errorf("Failed to connect; is skywire running?: %v", err)) + } + url = fmt.Sprintf("http://127.0.0.1%s/#/vpn/%s/", clivisor.HypervisorPort(cmd.Flags()), overview.PubKey.Hex()) + } + if err := webbrowser.Open(url); err != nil { + internal.PrintFatalError(cmd.Flags(), fmt.Errorf("Failed to open VPN UI in browser:: %v", err)) + } + }, +} + +var vpnURLCmd = &cobra.Command{ + Use: "url", + Short: "Show VPN UI URL", + Run: func(cmd *cobra.Command, _ []string) { + var url string + if isPkg { + path = visorconfig.SkywireConfig() + } + if path != "" { + conf, err := visorconfig.ReadFile(path) + if err != nil { + internal.PrintFatalError(cmd.Flags(), fmt.Errorf("Failed to read in config: %v", err)) + } + url = fmt.Sprintf("http://127.0.0.1%s/#/vpn/%s/", clivisor.HypervisorPort(cmd.Flags()), conf.PK.Hex()) + } else { + rpcClient, err := clirpc.Client(cmd.Flags()) + if err != nil { + os.Exit(1) + } + overview, err := rpcClient.Overview() + if err != nil { + internal.PrintFatalRPCError(cmd.Flags(), err) + } + url = fmt.Sprintf("http://127.0.0.1%s/#/vpn/%s/", clivisor.HypervisorPort(cmd.Flags()), overview.PubKey.Hex()) + } + + output := struct { + URL string `json:"url"` + }{ + URL: url, + } + + internal.PrintOutput(cmd.Flags(), output, fmt.Sprintln(url)) + }, +} diff --git a/go.mod b/go.mod index 9a699a934e..f6c65c6f23 100644 --- a/go.mod +++ b/go.mod @@ -55,7 +55,6 @@ require ( github.com/spf13/pflag v1.0.5 github.com/zcalusic/sysinfo v0.9.5 golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde - periph.io/x/periph v3.6.8+incompatible ) require ( diff --git a/go.sum b/go.sum index ccc5e05484..988e058c87 100644 --- a/go.sum +++ b/go.sum @@ -542,7 +542,6 @@ github.com/skycoin/noise v0.0.0-20180327030543-2492fe189ae6 h1:1Nc5EBY6pjfw1kwW0 github.com/skycoin/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:UXghlricA7J3aRD/k7p/zBObQfmBawwCxIVPVjz2Q3o= github.com/skycoin/skycoin v0.27.1 h1:HatxsRwVSPaV4qxH6290xPBmkH/HgiuAoY2qC+e8C9I= github.com/skycoin/skycoin v0.27.1/go.mod h1:78nHjQzd8KG0jJJVL/j0xMmrihXi70ti63fh8vXScJw= -github.com/skycoin/skywire-utilities v0.0.0-20230110132024-c5536ba8e22c h1:jYHyLwSyRVR/TmT4WWIGAeFX4FawGHA4Gaeic0zX3KI= github.com/skycoin/skywire-utilities v0.0.0-20230110132024-c5536ba8e22c/go.mod h1:X5H+fKC3rD11/sm4t9V2FWy/aet7OdEilaO2Ar3waXY= github.com/skycoin/skywire-utilities v0.0.0-20230315234948-7c62dc34c53a h1:hTqQ+8G/2Y+vd4qXoTbm7gfj+mjil2zDnGSS8i8V4LQ= github.com/skycoin/skywire-utilities v0.0.0-20230315234948-7c62dc34c53a/go.mod h1:X5H+fKC3rD11/sm4t9V2FWy/aet7OdEilaO2Ar3waXY= @@ -1145,8 +1144,6 @@ howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM= howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= nhooyr.io/websocket v1.8.2 h1:LwdzfyyOZKtVFoXay6A39Acu03KmidSZ3YUUvPa13PA= nhooyr.io/websocket v1.8.2/go.mod h1:LiqdCg1Cu7TPWxEvPjPa0TGYxCsy4pHNTN9gGluwBpQ= -periph.io/x/periph v3.6.8+incompatible h1:lki0ie6wHtvlilXhIkabdCUQMpb5QN4Fx33yNQdqnaA= -periph.io/x/periph v3.6.8+incompatible/go.mod h1:EWr+FCIU2dBWz5/wSWeiIUJTriYv9v2j2ENBmgYyy7Y= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= diff --git a/pkg/skyenv/skyenv.go b/pkg/skyenv/skyenv.go index 4be52f5222..246613d9f6 100644 --- a/pkg/skyenv/skyenv.go +++ b/pkg/skyenv/skyenv.go @@ -114,9 +114,19 @@ const ( NodeInfoSha256 string = "node-info.sha" ) +// SkywireConfig returns the full path to the package config +func SkywireConfig() string { + return SkywirePath + "/" + ConfigJSON +} + +// SkyEnvs returns the full path to the environmental variable file +func SkyEnvs() string { + return SkyenvFilePath + "/" + SkyenvFile +} + // PkgConfig struct contains paths specific to the installation type PkgConfig struct { - LauncherBinPath `json:"launcher"` + LauncherBinPath string `json:"launcher"` LocalPath string `json:"local_path"` Hypervisor `json:"hypervisor"` // TLSCertFile string `json:"tls_cert_file"` diff --git a/pkg/skyenv/skyenv_darwin.go b/pkg/skyenv/skyenv_darwin.go new file mode 100644 index 0000000000..7517a32bfe --- /dev/null +++ b/pkg/skyenv/skyenv_darwin.go @@ -0,0 +1,34 @@ +//go:build darwin +// +build darwin + +// Package skyenv defines variables and constants +package skyenv + +const ( + //OS detection at runtime + OS = "mac" + // SkywirePath is the path to the installation folder. + SkywirePath = "/Library/Application Support/Skywire" + // ConfigJSON is the config name generated by the script included with the installation on mac + ConfigJSON = "skywire-config.json" + + //TODO: @mrpalide set this correctly for macos. it shouldn't be in the installed path + + // SkyenvFilePath is the path to the SkyenvFile + SkyenvFilePath = "/Library/Application Support/Skywire" + // SkyenvFile contains environmental variables which are detected by `skywire-autoconfig` / `skywire-cli config auto` to set default or persistent values + SkyenvFile = "skyenv.sh" +) + +// PackageConfig contains installation paths (for mac) +func PackageConfig() PkgConfig { + pkgConfig := PkgConfig{ + LauncherBinPath: "/Applications/Skywire.app/Contents/MacOS/apps", + LocalPath: "/Library/Application Support/Skywire/local", + Hypervisor: Hypervisor{ + DbPath: "/Library/Application Support/Skywire/users.db", + EnableAuth: true, + }, + } + return pkgConfig +} diff --git a/pkg/skyenv/skyenv_linux.go b/pkg/skyenv/skyenv_linux.go new file mode 100644 index 0000000000..a352aaeea6 --- /dev/null +++ b/pkg/skyenv/skyenv_linux.go @@ -0,0 +1,31 @@ +//go:build linux +// +build linux + +// Package skyenv defines variables and constants +package skyenv + +const ( + //OS detection at runtime + OS = "linux" + // SkywirePath is the path to the installation folder for the linux packages. + SkywirePath = "/opt/skywire" + // ConfigJSON is the config name generated by the skywire-autocofig script in the linux packages + ConfigJSON = "skywire.json" + // SkyenvFilePath is the path to the SkyenvFile + SkyenvFilePath = "/etc/profile.d" + // SkyenvFile contains environmental variables which are detected by `skywire-autoconfig` / `skywire-cli config auto` to set default or persistent values + SkyenvFile = "skyenv.sh" +) + +// PackageConfig contains installation paths (for linux) +func PackageConfig() PkgConfig { + pkgConfig := PkgConfig{ + LauncherBinPath: "/opt/skywire/apps", + LocalPath: "/opt/skywire/local", + Hypervisor: Hypervisor{ + DbPath: "/opt/skywire/users.db", + EnableAuth: true, + }, + } + return pkgConfig +} diff --git a/pkg/skyenv/skyenv_windows.go b/pkg/skyenv/skyenv_windows.go new file mode 100644 index 0000000000..8ac6adf91f --- /dev/null +++ b/pkg/skyenv/skyenv_windows.go @@ -0,0 +1,34 @@ +//go:build windows +// +build windows + +// Package skyenv defines variables and constants +package skyenv + +const ( + //OS detection at runtime + OS = "win" + // SkywirePath is the path to the installation folder for the .msi + SkywirePath = "C:/Program Files/Skywire" + // ConfigJSON is the config name generated by the batch file included with the windows .msi + ConfigJSON = "skywire-config.json" + + //TODO: @mrpalide set this correctly for windows. it shouldn't be in the installed path + + // SkyenvFilePath is the path to the SkyenvFile + SkyenvFilePath = "C:/Program Files/Skywire" + // SkyenvFile contains environmental variables which are detected by `skywire-autoconfig` / `skywire-cli config auto` to set default or persistent values + SkyenvFile = "skyenv.bat" +) + +// PackageConfig contains installation paths (for windows) +func PackageConfig() PkgConfig { + pkgConfig := PkgConfig{ + LauncherBinPath: "C:/Program Files/Skywire/apps", + LocalPath: "C:/Program Files/Skywire/local", + Hypervisor: Hypervisor{ + DbPath: "C:/Program Files/Skywire/users.db", + EnableAuth: true, + }, + } + return pkgConfig +} diff --git a/pkg/visor/api.go b/pkg/visor/api.go index 95fa3bb4cc..03f812ebb8 100644 --- a/pkg/visor/api.go +++ b/pkg/visor/api.go @@ -89,6 +89,7 @@ type API interface { //skysocks-client controls StartSkysocksClient(pk string) error StopSkysocksClient() error + ProxyServers(version, country string) ([]servicedisc.Service, error) //transports TransportTypes() ([]string, error) @@ -916,6 +917,27 @@ func (v *Visor) VPNServers(version, country string) ([]servicedisc.Service, erro return vpnServers, nil } +// ProxyServers gets available public VPN server from service discovery URL +func (v *Visor) ProxyServers(version, country string) ([]servicedisc.Service, error) { + log := logging.MustGetLogger("proxyservers") + vLog := logging.NewMasterLogger() + vLog.SetLevel(logrus.InfoLevel) + + sdClient := servicedisc.NewClient(log, vLog, servicedisc.Config{ + Type: servicedisc.ServiceTypeProxy, + PK: v.conf.PK, + SK: v.conf.SK, + DiscAddr: v.conf.Launcher.ServiceDisc, + DisplayNodeIP: v.conf.Launcher.DisplayNodeIP, + }, &http.Client{Timeout: time.Duration(20) * time.Second}, "") + proxyServers, err := sdClient.Services(context.Background(), 0, version, country) + if err != nil { + v.log.Error("Error getting public vpn servers: ", err) + return nil, err + } + return proxyServers, nil +} + // PublicVisors gets available public public visors from service discovery URL func (v *Visor) PublicVisors(version, country string) ([]servicedisc.Service, error) { log := logging.MustGetLogger("public_visors") diff --git a/pkg/visor/rpc.go b/pkg/visor/rpc.go index 5be8726979..2c008a16ae 100644 --- a/pkg/visor/rpc.go +++ b/pkg/visor/rpc.go @@ -635,14 +635,14 @@ func (r *RPC) SetPublicAutoconnect(pAc *bool, _ *struct{}) (err error) { return err } -// FilterVPNServersIn is input for VPNServers -type FilterVPNServersIn struct { +// FilterServersIn is input for VPNServers and ProxyServers +type FilterServersIn struct { Version string Country string } // VPNServers gets available public VPN server from service discovery URL -func (r *RPC) VPNServers(vc *FilterVPNServersIn, out *[]servicedisc.Service) (err error) { +func (r *RPC) VPNServers(vc *FilterServersIn, out *[]servicedisc.Service) (err error) { defer rpcutil.LogCall(r.log, "VPNServers", nil)(out, &err) vpnServers, err := r.visor.VPNServers(vc.Version, vc.Country) if vpnServers != nil { @@ -651,6 +651,16 @@ func (r *RPC) VPNServers(vc *FilterVPNServersIn, out *[]servicedisc.Service) (er return err } +// ProxyServers gets available socks5 proxy servers from service discovery URL +func (r *RPC) ProxyServers(vc *FilterServersIn, out *[]servicedisc.Service) (err error) { + defer rpcutil.LogCall(r.log, "ProxyServers", nil)(out, &err) + proxyServers, err := r.visor.ProxyServers(vc.Version, vc.Country) + if proxyServers != nil { + *out = proxyServers + } + return err +} + // RemoteVisors return connected remote visors func (r *RPC) RemoteVisors(_ *struct{}, out *[]string) (err error) { defer rpcutil.LogCall(r.log, "RemoteVisor", nil)(out, &err) diff --git a/pkg/visor/rpc_client.go b/pkg/visor/rpc_client.go index 92771da9ec..2c0f5c170f 100644 --- a/pkg/visor/rpc_client.go +++ b/pkg/visor/rpc_client.go @@ -489,7 +489,17 @@ type StatusMessage struct { // VPNServers calls VPNServers. func (rc *rpcClient) VPNServers(version, country string) ([]servicedisc.Service, error) { output := []servicedisc.Service{} - err := rc.Call("VPNServers", &FilterVPNServersIn{ // nolint + err := rc.Call("VPNServers", &FilterServersIn{ // nolint + Version: version, + Country: country, + }, &output) + return output, err +} + +// ProxyServers calls ProxyServers. +func (rc *rpcClient) ProxyServers(version, country string) ([]servicedisc.Service, error) { + output := []servicedisc.Service{} + err := rc.Call("ProxyServers", &FilterServersIn{ // nolint Version: version, Country: country, }, &output) @@ -1219,6 +1229,11 @@ func (mc *mockRPCClient) VPNServers(_, _ string) ([]servicedisc.Service, error) return []servicedisc.Service{}, nil } +// ProxyServers implements API +func (mc *mockRPCClient) ProxyServers(_, _ string) ([]servicedisc.Service, error) { + return []servicedisc.Service{}, nil +} + // RemoteVisors implements API func (mc *mockRPCClient) RemoteVisors() ([]string, error) { return []string{}, nil diff --git a/pkg/visor/visorconfig/survey.go b/pkg/visor/visorconfig/survey.go index c86c2aef73..c1a1b6cecb 100644 --- a/pkg/visor/visorconfig/survey.go +++ b/pkg/visor/visorconfig/survey.go @@ -1,3 +1,4 @@ +// Package visorconfig pkg/visor/visorconfig/survey.go package visorconfig import ( diff --git a/pkg/visor/visorconfig/values.go b/pkg/visor/visorconfig/values.go index bedc17370a..21ebca578f 100644 --- a/pkg/visor/visorconfig/values.go +++ b/pkg/visor/visorconfig/values.go @@ -22,6 +22,17 @@ import ( ) var ( + //OS detection at runtime + OS = skyenv.OS + // SkywirePath is the path to the installation folder for the linux packages. + SkywirePath = skyenv.SkywirePath + // ConfigJSON is the config name generated by the skywire-autocofig script in the linux packages + ConfigJSON = skyenv.ConfigJSON + // SkyenvFilePath is the path to the SkyenvFile + SkyenvFilePath = skyenv.SkyenvFilePath + // SkyenvFile contains environmental variables which are detected by `skywire-autoconfig` / `skywire-cli config auto` to set default or persistent values + SkyenvFile = skyenv.SkyenvFile + // config file constants // ConfigName is the default config name. Updated by setting config file path. @@ -138,6 +149,11 @@ var ( RewardFile = skyenv.RewardFile ) +// SkywireConfig returns the full path to the package config +func SkywireConfig() string { + return SkywirePath + "/" + ConfigJSON +} + // PkgConfig struct contains paths specific to the linux packages type PkgConfig struct { LauncherBinPath string `json:"launcher"` @@ -199,9 +215,9 @@ func HomePath() string { } // Config returns either UserConfig or PackageConfig based on permissions -func Config() PkgConfig { +func Config() skyenv.PkgConfig { if IsRoot() { - return PackageConfig() + return skyenv.PackageConfig() } return UserConfig() } @@ -304,3 +320,13 @@ var ( // VisorConfigFile will contain the path to the visor's config or `stdin` to denote that the config was read from STDIN VisorConfigFile string ) + +// PackageConfig returns the package-specific config paths +func PackageConfig() skyenv.PkgConfig { + return skyenv.PackageConfig() +} + +// UpdateCommand returns the commands which are run when the update button is clicked in the ui +func UpdateCommand() []string { + return []string{`echo "not implemented"`} +} diff --git a/pkg/visor/visorconfig/values_darwin.go b/pkg/visor/visorconfig/values_darwin.go index 1941314acd..cee5345b25 100644 --- a/pkg/visor/visorconfig/values_darwin.go +++ b/pkg/visor/visorconfig/values_darwin.go @@ -10,53 +10,15 @@ import ( "github.com/jaypipes/ghw" "github.com/skycoin/skywire-utilities/pkg/cipher" + "github.com/skycoin/skywire/pkg/skyenv" ) -const ( - //OS detection at runtime - OS = "mac" - // SkywirePath is the path to the installation folder. - SkywirePath = "/Library/Application Support/Skywire" - // ConfigJSON is the config name generated by the script included with the installation on mac - ConfigJSON = "skywire-config.json" - - //TODO: @mrpalide set this correctly for macos. it shouldn't be in the installed path - - // SkyenvFilePath is the path to the SkyenvFile - SkyenvFilePath = "/Library/Application Support/Skywire" - // SkyenvFile contains environmental variables which are detected by `skywire-autoconfig` / `skywire-cli config auto` to set default or persistent values - SkyenvFile = "skyenv.sh" -) - -// SkywireConfig returns the full path to the package config -func SkywireConfig() string { - return SkywirePath + "/" + ConfigJSON -} - -// SkyEnvs returns the full path to the environmental variable file -func SkyEnvs() string { - return SkyenvFilePath + "/" + SkyenvFile -} - -// PackageConfig contains installation paths (for mac) -func PackageConfig() PkgConfig { - pkgConfig := PkgConfig{ - LauncherBinPath: "/Applications/Skywire.app/Contents/MacOS/apps", - LocalPath: "/Library/Application Support/Skywire/local", - Hypervisor: Hypervisor{ - DbPath: "/Library/Application Support/Skywire/users.db", - EnableAuth: true, - }, - } - return pkgConfig -} - -// UserConfig contains installation paths (for mac) -func UserConfig() PkgConfig { - usrConfig := PkgConfig{ +// UserConfig contains installation paths for running skywire as the user +func UserConfig() skyenv.PkgConfig { + usrConfig := skyenv.PkgConfig{ LauncherBinPath: "/Applications/Skywire.app/Contents/MacOS/apps", LocalPath: HomePath() + "/.skywire/local", - Hypervisor: Hypervisor{ + Hypervisor: skyenv.Hypervisor{ DbPath: HomePath() + "/.skywire/users.db", EnableAuth: true, }, @@ -64,11 +26,6 @@ func UserConfig() PkgConfig { return usrConfig } -// UpdateCommand returns the commands which are run when the update button is clicked in the ui -func UpdateCommand() []string { - return []string{`echo "update not implemented for macOS. Download a new version from the release section here: https://github.com/skycoin/skywire/releases"`} -} - // Survey system hardware survey struct type Survey struct { PubKey cipher.PubKey `json:"public_key,omitempty"` diff --git a/pkg/visor/visorconfig/values_linux.go b/pkg/visor/visorconfig/values_linux.go index 31b7c0263a..39f61f1d0d 100644 --- a/pkg/visor/visorconfig/values_linux.go +++ b/pkg/visor/visorconfig/values_linux.go @@ -10,53 +10,17 @@ import ( "github.com/google/uuid" "github.com/jaypipes/ghw" "github.com/zcalusic/sysinfo" - "periph.io/x/periph/host/distro" "github.com/skycoin/skywire-utilities/pkg/cipher" + "github.com/skycoin/skywire/pkg/skyenv" ) -const ( - //OS detection at runtime - OS = "linux" - // SkywirePath is the path to the installation folder for the linux packages. - SkywirePath = "/opt/skywire" - // ConfigJSON is the config name generated by the skywire-autocofig script in the linux packages - ConfigJSON = "skywire.json" - // SkyenvFilePath is the path to the SkyenvFile - SkyenvFilePath = "/etc/profile.d" - // SkyenvFile contains environmental variables which are detected by `skywire-autoconfig` / `skywire-cli config auto` to set default or persistent values - SkyenvFile = "skyenv.sh" -) - -// SkywireConfig returns the full path to the package config -func SkywireConfig() string { - return SkywirePath + "/" + ConfigJSON -} - -// SkyEnvs returns the full path to the environmental variable file -func SkyEnvs() string { - return SkyenvFilePath + "/" + SkyenvFile -} - -// PackageConfig contains installation paths (for linux) -func PackageConfig() PkgConfig { - pkgConfig := PkgConfig{ - LauncherBinPath: "/opt/skywire/apps", - LocalPath: "/opt/skywire/local", - Hypervisor: Hypervisor{ - DbPath: "/opt/skywire/users.db", - EnableAuth: true, - }, - } - return pkgConfig -} - -// UserConfig contains installation paths (for linux) -func UserConfig() PkgConfig { - usrConfig := PkgConfig{ +// UserConfig contains installation paths for running skywire as the user +func UserConfig() skyenv.PkgConfig { + usrConfig := skyenv.PkgConfig{ LauncherBinPath: "/opt/skywire/apps", LocalPath: HomePath() + "/.skywire/local", - Hypervisor: Hypervisor{ + Hypervisor: skyenv.Hypervisor{ DbPath: HomePath() + "/.skywire/users.db", EnableAuth: true, }, @@ -64,16 +28,6 @@ func UserConfig() PkgConfig { return usrConfig } -// UpdateCommand returns the commands which are run when the update button is clicked in the ui -func UpdateCommand() []string { - if distro.IsArmbian() || distro.IsDebian() || distro.IsRaspbian() || distro.IsUbuntu() { - //enabling install-skyire.service and rebooting is required to avoid interrupting an update when the running visor is stopped - //install-skywire.service is provided by the skybian package and calls install-skywire.sh - return []string{`systemctl enable install-skywire.service && systemctl reboot || echo -e "Resource unavailable.\nPlease update manually as specified here:\nhttps://github.com/skycoin/skywire/wiki/Skywire-Package-Installation"`} - } - return []string{`echo -e "Update not implemented for this linux distro.\nPlease update skywire the same way you installed it."`} -} - // Survey system hardware survey struct type Survey struct { Timestamp time.Time `json:"timestamp"` @@ -104,7 +58,7 @@ func SystemSurvey() (Survey, error) { return Survey{}, err } memory, err := ghw.Memory() - if err != nil && err.Error() != "Could not determine total usable bytes of memory" { + if err != nil { return Survey{}, err } for { diff --git a/pkg/visor/visorconfig/values_windows.go b/pkg/visor/visorconfig/values_windows.go index 0ec094c07f..7528799f8d 100644 --- a/pkg/visor/visorconfig/values_windows.go +++ b/pkg/visor/visorconfig/values_windows.go @@ -10,53 +10,15 @@ import ( "github.com/jaypipes/ghw" "github.com/skycoin/skywire-utilities/pkg/cipher" + "github.com/skycoin/skywire/pkg/skyenv" ) -const ( - //OS detection at runtime - OS = "win" - // SkywirePath is the path to the installation folder for the .msi - SkywirePath = "C:/Program Files/Skywire" - // ConfigJSON is the config name generated by the batch file included with the windows .msi - ConfigJSON = "skywire-config.json" - - //TODO: @mrpalide set this correctly for windows. it shouldn't be in the installed path - - // SkyenvFilePath is the path to the SkyenvFile - SkyenvFilePath = "C:/Program Files/Skywire" - // SkyenvFile contains environmental variables which are detected by `skywire-autoconfig` / `skywire-cli config auto` to set default or persistent values - SkyenvFile = "skyenv.bat" -) - -// SkywireConfig returns the full path to the package config -func SkywireConfig() string { - return SkywirePath + "/" + ConfigJSON -} - -// SkyEnvs returns the full path to the environmental variable file -func SkyEnvs() string { - return SkyenvFilePath + "/" + SkyenvFile -} - -// PackageConfig contains installation paths (for windows) -func PackageConfig() PkgConfig { - pkgConfig := PkgConfig{ - LauncherBinPath: "C:/Program Files/Skywire/apps", - LocalPath: "C:/Program Files/Skywire/local", - Hypervisor: Hypervisor{ - DbPath: "C:/Program Files/Skywire/users.db", - EnableAuth: true, - }, - } - return pkgConfig -} - -// UserConfig contains installation paths (for windows) -func UserConfig() PkgConfig { - usrConfig := PkgConfig{ +// UserConfig contains installation paths for running skywire as the user +func UserConfig() skyenv.PkgConfig { + usrConfig := skyenv.PkgConfig{ LauncherBinPath: "C:/Program Files/Skywire/apps", LocalPath: HomePath() + "/.skywire/local", - Hypervisor: Hypervisor{ + Hypervisor: skyenv.Hypervisor{ DbPath: HomePath() + "/.skywire/users.db", EnableAuth: true, }, @@ -64,11 +26,6 @@ func UserConfig() PkgConfig { return usrConfig } -// UpdateCommand returns the commands which are run when the update button is clicked in the ui -func UpdateCommand() []string { - return []string{`echo "Update not implemented for windows. Download a new version from the release section here: https://github.com/skycoin/skywire/releases"`} -} - // Survey system hardware survey struct type Survey struct { PubKey cipher.PubKey `json:"public_key,omitempty"` diff --git a/vendor/modules.txt b/vendor/modules.txt index 325c6c0579..d52aa1b4f4 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -462,6 +462,3 @@ nhooyr.io/websocket/internal/bpool nhooyr.io/websocket/internal/errd nhooyr.io/websocket/internal/wsjs nhooyr.io/websocket/internal/xsync -# periph.io/x/periph v3.6.8+incompatible -## explicit -periph.io/x/periph/host/distro diff --git a/vendor/periph.io/x/periph/AUTHORS b/vendor/periph.io/x/periph/AUTHORS deleted file mode 100644 index e8ff861edc..0000000000 --- a/vendor/periph.io/x/periph/AUTHORS +++ /dev/null @@ -1,15 +0,0 @@ -# This is the list of The Periph Authors for copyright purposes. -# -# This does not necessarily list everyone who has contributed code, since in -# some cases, their employer may be the copyright holder. To see the full list -# of contributors, see the revision history in source control. -Cássio Botaro -Fractal Industries, Inc -Google Inc. -Josh Gardiner -Matt Aimonetti -Max Ekman -Rifiniti, Inc -Stephan Sperber -Thorsten von Eicken - diff --git a/vendor/periph.io/x/periph/CONTRIBUTORS b/vendor/periph.io/x/periph/CONTRIBUTORS deleted file mode 100644 index 2e86a9bcbc..0000000000 --- a/vendor/periph.io/x/periph/CONTRIBUTORS +++ /dev/null @@ -1,41 +0,0 @@ -# This is the official list of people who can contribute -# (and typically have contributed) code to the periph repository. -# The AUTHORS file lists the copyright holders; this file -# lists people. For example, Google employees are listed here -# but not in AUTHORS, because Google holds the copyright. -# -# Names should be added to this file only after verifying that -# the individual or the individual's organization has agreed to -# the appropriate Contributor License Agreement, found here: -# -# https://cla.developers.google.com/ -# -# When adding J Random Contributor's name to this file, -# either J's name or J's organization's name should be -# added to the AUTHORS file, depending on whether the -# individual or corporate CLA was used. - -# Names should be added to this file like so: -# Individual's name -# Individual's name -# -# An entry with multiple email addresses specifies that the -# first address should be used in the submit logs and -# that the other addresses should be recognized as the -# same person when interacting with Gerrit. - -# Please keep the list sorted. - -Cássio Botaro -Eugene Dzhurynsky -Hidetoshi Shimokawa -John Maguire -Josh Gardiner -Marc-Antoine Ruel -Matt Aimonetti -Max Ekman -Matias Insaurralde -Seán C McCord -Stephan Sperber -Thorsten von Eicken - diff --git a/vendor/periph.io/x/periph/LICENSE b/vendor/periph.io/x/periph/LICENSE deleted file mode 100644 index d645695673..0000000000 --- a/vendor/periph.io/x/periph/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/vendor/periph.io/x/periph/host/distro/devtree.go b/vendor/periph.io/x/periph/host/distro/devtree.go deleted file mode 100644 index e8c2da4389..0000000000 --- a/vendor/periph.io/x/periph/host/distro/devtree.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2016 The Periph Authors. All rights reserved. -// Use of this source code is governed under the Apache License, Version 2.0 -// that can be found in the LICENSE file. - -package distro - -import ( - "encoding/binary" - "io/ioutil" -) - -// DTModel returns platform model info from the Linux device tree (/proc/device-tree/model), and -// returns "unknown" on non-linux systems or if the file is missing. -func DTModel() string { - mu.Lock() - defer mu.Unlock() - - if dtModel == "" { - dtModel = "" - if isLinux { - dtModel = makeDTModelLinux() - } - } - return dtModel -} - -// DTCompatible returns platform compatibility info from the Linux device tree -// (/proc/device-tree/compatible), and returns []{"unknown"} on non-linux systems or if the file is -// missing. -func DTCompatible() []string { - mu.Lock() - defer mu.Unlock() - - if dtCompatible == nil { - dtCompatible = []string{} - if isLinux { - dtCompatible = makeDTCompatible() - } - } - return dtCompatible -} - -// DTRevision returns the device revision (e.g. a02082 for the Raspberry Pi 3) -// from the Linux device tree, or 0 if the file is missing or malformed. -func DTRevision() uint32 { - mu.Lock() - defer mu.Unlock() - - if dtRevisionRead { - return dtRevision - } - dtRevisionRead = true - if b, _ := ioutil.ReadFile("/proc/device-tree/system/linux,revision"); len(b) >= 4 { - dtRevision = binary.BigEndian.Uint32(b[:4]) - } - return dtRevision -} - -// - -var ( - dtModel string // cached /proc/device-tree/model - dtCompatible []string // cached /proc/device-tree/compatible - dtRevision uint32 // cached /proc/device-tree/system/linux,revision - dtRevisionRead bool -) - -func makeDTModelLinux() string { - // Read model from device tree. - if bytes, err := readFile("/proc/device-tree/model"); err == nil { - if model := splitNull(bytes); len(model) > 0 { - return model[0] - } - } - return "" -} - -func makeDTCompatible() []string { - // Read compatible from device tree. - if bytes, err := readFile("/proc/device-tree/compatible"); err == nil { - return splitNull(bytes) - } - return []string{} -} diff --git a/vendor/periph.io/x/periph/host/distro/distro.go b/vendor/periph.io/x/periph/host/distro/distro.go deleted file mode 100644 index 96e49dfbf9..0000000000 --- a/vendor/periph.io/x/periph/host/distro/distro.go +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright 2016 The Periph Authors. All rights reserved. -// Use of this source code is governed under the Apache License, Version 2.0 -// that can be found in the LICENSE file. - -// Package distro implements common functionality to auto-detect features on -// the host; generally about linux distributions. -// -// Most of the functions exported as in the form IsFoo() where Foo is a linux -// distribution. -package distro - -import ( - "io/ioutil" - "os" - "strconv" - "strings" - "sync" - "unicode" -) - -// IsArmbian returns true if running on a Armbian distribution. -// -// http://www.armbian.com/ -func IsArmbian() bool { - if isArm && isLinux { - // Armbian presents itself as debian in /etc/os-release so OSRelease() - // cannot be used.. - _, err := os.Stat("/etc/armbian.txt") - return err == nil - } - return false -} - -// IsDebian returns true if running on an Debian derived distribution. -// -// This function returns true on both Armbian, Raspbian and Ubuntu. -// -// https://debian.org/ -func IsDebian() bool { - if isLinux { - // http://0pointer.de/public/systemd-man/os-release.html#ID_LIKE= - if OSRelease()["ID"] == "debian" { - return true - } - for _, part := range strings.Split(OSRelease()["ID_LIKE"], " ") { - if part == "debian" { - return true - } - } - } - return false -} - -// IsRaspbian returns true if running on a Raspbian distribution. -// -// https://raspbian.org/ -func IsRaspbian() bool { - if isArm && isLinux { - return OSRelease()["ID"] == "raspbian" - } - return false -} - -// IsUbuntu returns true if running on an Ubuntu derived distribution. -// -// https://ubuntu.com/ -func IsUbuntu() bool { - if isLinux { - return OSRelease()["ID"] == "ubuntu" - } - return false -} - -// OSRelease returns parsed data from /etc/os-release. -// -// For more information, see -// http://0pointer.de/public/systemd-man/os-release.html -func OSRelease() map[string]string { - if isLinux { - return makeOSReleaseLinux() - } - return osRelease -} - -// CPU - -// CPUInfo returns parsed data from /proc/cpuinfo. -func CPUInfo() map[string]string { - if isLinux { - return makeCPUInfoLinux() - } - return cpuInfo -} - -// - -var ( - mu sync.Mutex - cpuInfo map[string]string - osRelease map[string]string - readFile = ioutil.ReadFile -) - -func splitSemiColon(content string) map[string]string { - // Strictly speaking this format isn't ok, there can be multiple group. - out := map[string]string{} - for _, line := range strings.Split(content, "\n") { - parts := strings.SplitN(line, ":", 2) - if len(parts) != 2 { - continue - } - // This format may have space around the ':'. - key := strings.TrimRightFunc(parts[0], unicode.IsSpace) - if len(key) == 0 || key[0] == '#' { - continue - } - // Ignore duplicate keys. - // TODO(maruel): Keep them all. - if _, ok := out[key]; !ok { - // Trim on both side, trailing space was observed on "Features" value. - out[key] = strings.TrimFunc(parts[1], unicode.IsSpace) - } - } - return out -} - -func splitStrict(content string) map[string]string { - out := map[string]string{} - for _, line := range strings.Split(content, "\n") { - parts := strings.SplitN(line, "=", 2) - if len(parts) != 2 { - continue - } - key := parts[0] - if len(key) == 0 || key[0] == '#' { - continue - } - // Overwrite previous key. - value := parts[1] - if len(value) > 2 && value[0] == '"' && value[len(value)-1] == '"' { - // Not exactly 100% right but #closeenough. See for more details - // https://www.freedesktop.org/software/systemd/man/os-release.html - var err error - value, err = strconv.Unquote(value) - if err != nil { - continue - } - } - out[key] = value - } - return out -} - -// splitNull returns the null-terminated strings in the data -func splitNull(data []byte) []string { - ss := strings.Split(string(data), "\x00") - // The last string is typically null-terminated, so remove empty string - // from end of array. - if len(ss) > 0 && len(ss[len(ss)-1]) == 0 { - ss = ss[:len(ss)-1] - } - return ss -} - -func makeCPUInfoLinux() map[string]string { - mu.Lock() - defer mu.Unlock() - if cpuInfo == nil { - cpuInfo = map[string]string{} - if bytes, err := readFile("/proc/cpuinfo"); err == nil { - cpuInfo = splitSemiColon(string(bytes)) - } - } - return cpuInfo -} - -func makeOSReleaseLinux() map[string]string { - mu.Lock() - defer mu.Unlock() - if osRelease == nil { - // This file may not exist on older distros. Send a PR if you want to have - // a specific fallback. - osRelease = map[string]string{} - if bytes, err := readFile("/etc/os-release"); err == nil { - osRelease = splitStrict(string(bytes)) - } - } - return osRelease -} diff --git a/vendor/periph.io/x/periph/host/distro/distro_arm.go b/vendor/periph.io/x/periph/host/distro/distro_arm.go deleted file mode 100644 index 90a23351f0..0000000000 --- a/vendor/periph.io/x/periph/host/distro/distro_arm.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2016 The Periph Authors. All rights reserved. -// Use of this source code is governed under the Apache License, Version 2.0 -// that can be found in the LICENSE file. - -package distro - -const isArm = true diff --git a/vendor/periph.io/x/periph/host/distro/distro_arm64.go b/vendor/periph.io/x/periph/host/distro/distro_arm64.go deleted file mode 100644 index d5734bc040..0000000000 --- a/vendor/periph.io/x/periph/host/distro/distro_arm64.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2016 The Periph Authors. All rights reserved. -// Use of this source code is governed under the Apache License, Version 2.0 -// that can be found in the LICENSE file. - -// +build arm64 - -package distro - -const isArm = true diff --git a/vendor/periph.io/x/periph/host/distro/distro_linux.go b/vendor/periph.io/x/periph/host/distro/distro_linux.go deleted file mode 100644 index 7679a8fd84..0000000000 --- a/vendor/periph.io/x/periph/host/distro/distro_linux.go +++ /dev/null @@ -1,7 +0,0 @@ -// Copyright 2016 The Periph Authors. All rights reserved. -// Use of this source code is governed under the Apache License, Version 2.0 -// that can be found in the LICENSE file. - -package distro - -const isLinux = true diff --git a/vendor/periph.io/x/periph/host/distro/distro_nonarm.go b/vendor/periph.io/x/periph/host/distro/distro_nonarm.go deleted file mode 100644 index 075cad554c..0000000000 --- a/vendor/periph.io/x/periph/host/distro/distro_nonarm.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2016 The Periph Authors. All rights reserved. -// Use of this source code is governed under the Apache License, Version 2.0 -// that can be found in the LICENSE file. - -// +build !arm,!arm64 - -package distro - -const isArm = false diff --git a/vendor/periph.io/x/periph/host/distro/distro_nonlinux.go b/vendor/periph.io/x/periph/host/distro/distro_nonlinux.go deleted file mode 100644 index 7fd1599e08..0000000000 --- a/vendor/periph.io/x/periph/host/distro/distro_nonlinux.go +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2016 The Periph Authors. All rights reserved. -// Use of this source code is governed under the Apache License, Version 2.0 -// that can be found in the LICENSE file. - -// +build !linux - -package distro - -const isLinux = false