Skip to content

Commit

Permalink
Fix IP issue on survey (#1855)
Browse files Browse the repository at this point in the history
* update [email protected]

* add IPSkycoinFetchDmsg method

* fix panic

* use skyenv value instead hardcoded

* remove test config

* fix Mac and Windows issue on survey

* remove http mode on fetch IP, just keep dmsg mode

* change json field name from ip_addr to ip_address
  • Loading branch information
mrpalide authored Jul 13, 2024
1 parent 0c73e9a commit 99de0a1
Show file tree
Hide file tree
Showing 14 changed files with 265 additions and 101 deletions.
8 changes: 7 additions & 1 deletion cmd/skywire-cli/commands/survey/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/spf13/cobra"

"github.com/skycoin/skywire-utilities/pkg/logging"
"github.com/skycoin/skywire-utilities/pkg/skyenv"
"github.com/skycoin/skywire/cmd/skywire-cli/internal"
"github.com/skycoin/skywire/pkg/visor/visorconfig"
)
Expand All @@ -18,6 +19,7 @@ var (
mLog = logging.NewMasterLogger()
log = mLog.PackageLogger("survey")
confPath string
dmsgDisc string
// stdin bool
// confArg string
pkg bool
Expand All @@ -30,6 +32,7 @@ var (
func init() {
surveyCmd.Flags().SortFlags = false
surveyCmd.Flags().StringVarP(&confPath, "config", "c", "", "optionl config file to use (i.e.: "+visorconfig.ConfigName+")")
surveyCmd.Flags().StringVar(&dmsgDisc, "dmsg-disc", skyenv.DmsgDiscAddr, "value of dmsg discovery")
// surveyCmd.Flags().StringVarP(&confArg, "confarg", "C", "", "supply config as argument")
// surveyCmd.Flags().BoolVarP(&stdin, "stdin", "n", false, "read config from stdin")
if _, err := os.Stat(visorconfig.SkywirePath + "/" + visorconfig.ConfigJSON); err == nil {
Expand Down Expand Up @@ -83,7 +86,10 @@ var surveyCmd = &cobra.Command{
log.WithError(err).Fatal("Failed to unmarshal old config json")
}
}
survey, err := visorconfig.SystemSurvey()
if conf != nil {
dmsgDisc = conf.Dmsg.Discovery
}
survey, err := visorconfig.SystemSurvey(dmsgDisc)
if err != nil {
internal.Catch(cmd.Flags(), fmt.Errorf("Failed to generate system survey: %v", err))
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ require (
github.com/pterm/pterm v0.12.66
github.com/robert-nix/ansihtml v1.0.1
github.com/sirupsen/logrus v1.9.3
github.com/skycoin/dmsg v1.3.22-0.20240702162730-1c2fcecd4bb6
github.com/skycoin/dmsg v1.3.24
github.com/skycoin/skycoin v0.27.1
github.com/skycoin/skycoin-service-discovery v0.0.0-20240627171358-7f59a951fa29
github.com/skycoin/skywire-services v0.0.0-20240627171623-87edf49d9025
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/skycoin/dmsg v1.3.22-0.20240702162730-1c2fcecd4bb6 h1:q+KeZyHWctCahSUbZ6b+iy1VQNHVKN2YZc7J2R0VIHw=
github.com/skycoin/dmsg v1.3.22-0.20240702162730-1c2fcecd4bb6/go.mod h1:72MC0HFDxKYqMLZ2RWGY/ZDNFq6965SP1PIrKlYqaiQ=
github.com/skycoin/dmsg v1.3.24 h1:aDa36UucXcWQCnHri1q5UKAVydomGDg28osBWlpUoOI=
github.com/skycoin/dmsg v1.3.24/go.mod h1:72MC0HFDxKYqMLZ2RWGY/ZDNFq6965SP1PIrKlYqaiQ=
github.com/skycoin/noise v0.0.0-20180327030543-2492fe189ae6 h1:1Nc5EBY6pjfw1kwW0duwyG+7WliWz5u9kgk1h5MnLuA=
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=
Expand Down
2 changes: 1 addition & 1 deletion pkg/visor/survey.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func GenerateSurvey(v *Visor, log *logging.Logger, routine bool) {
log.Info("Skycoin reward address: ", cAddr.String())
//generate the system survey
pathutil.EnsureDir(v.conf.LocalPath) //nolint
survey, err := visconf.SystemSurvey()
survey, err := visconf.SystemSurvey(v.conf.Dmsg.Discovery)
if err != nil {
log.WithError(err).Error("Could not read system info.")
return
Expand Down
114 changes: 34 additions & 80 deletions pkg/visor/visorconfig/values.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,23 @@
package visorconfig

import (
"encoding/json"
"context"
"fmt"
"io"
"net/http"
"os"
"os/exec"
"os/user"
"path/filepath"
"strings"
"time"

"github.com/bitfield/script"
"github.com/skycoin/dmsg/pkg/disc"
"github.com/skycoin/dmsg/pkg/dmsg"

"github.com/skycoin/skywire-utilities/pkg/buildinfo"
"github.com/skycoin/skywire-utilities/pkg/cipher"
"github.com/skycoin/skywire-utilities/pkg/cmdutil"
"github.com/skycoin/skywire-utilities/pkg/logging"
"github.com/skycoin/skywire/pkg/skyenv"
)

Expand Down Expand Up @@ -231,92 +232,45 @@ func IsRoot() bool {
return userLvl.Username == "root"
}

// IPAddr struct of `ip --json addr`
type IPAddr []struct {
Ifindex int `json:"ifindex"`
Ifname string `json:"ifname"`
Flags []string `json:"flags"`
Mtu int `json:"mtu"`
Qdisc string `json:"qdisc"`
Operstate string `json:"operstate"`
Group string `json:"group"`
Txqlen int `json:"txqlen"`
LinkType string `json:"link_type"`
Address string `json:"address"`
Broadcast string `json:"broadcast"`
AddrInfo []struct {
Family string `json:"family"`
Local string `json:"local"`
Prefixlen int `json:"prefixlen"`
Scope string `json:"scope"`
Label string `json:"label,omitempty"`
ValidLifeTime int64 `json:"valid_life_time"`
PreferredLifeTime int64 `json:"preferred_life_time"`
} `json:"addr_info"`
}
// FetchIP fetches the ip address by dmsg servers
func FetchIP(dmsgDisc string) (string, error) {
log := logging.MustGetLogger("ip_skycoin_fetch_dmsg")
ctx, cancel := cmdutil.SignalContext(context.Background(), nil)
defer cancel()

// IPA returns IPAddr struct filled in with the json response from `ip --json addr` command ; fail silently on errors
func IPA() (ip *IPAddr) {
//non-critical logic implemented with bitfield/script
ipa, err := script.Exec(`ip --json addr`).String()
if err != nil {
return nil
}
err = json.Unmarshal([]byte(ipa), &ip)
pk, sk := cipher.GenerateKeyPair()

dmsgC, closeDmsg, err := startDmsg(ctx, log, pk, sk, dmsgDisc)
if err != nil {
return nil
return "", fmt.Errorf("failed to start dmsg")
}
return ip
}
defer closeDmsg()

// IPSkycoin struct of ip.skycoin.com json
type IPSkycoin struct {
IPAddress string `json:"ip_address"`
Latitude float64 `json:"latitude"`
Longitude float64 `json:"longitude"`
PostalCode string `json:"postal_code"`
ContinentCode string `json:"continent_code"`
CountryCode string `json:"country_code"`
CountryName string `json:"country_name"`
RegionCode string `json:"region_code"`
RegionName string `json:"region_name"`
ProvinceCode string `json:"province_code"`
ProvinceName string `json:"province_name"`
CityName string `json:"city_name"`
Timezone string `json:"timezone"`
ip, err := dmsgC.LookupIP(ctx, nil)
return ip.String(), err
}

// IPSkycoinFetch fetches the json response from ip.skycoin.com
func IPSkycoinFetch() (ipskycoin *IPSkycoin) {
func startDmsg(ctx context.Context, log *logging.Logger, pk cipher.PubKey, sk cipher.SecKey, dmsgDisc string) (dmsgC *dmsg.Client, stop func(), err error) {
dmsgC = dmsg.NewClient(pk, sk, disc.NewHTTP(dmsgDisc, &http.Client{}, log), &dmsg.Config{MinSessions: dmsg.DefaultMinSessions})
go dmsgC.Serve(context.Background())

url := fmt.Sprint("http://", "ip.skycoin.com")
client := http.Client{
Timeout: time.Second * 45, // Timeout after 45 seconds
}
//create the http request
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return nil
stop = func() {
err := dmsgC.Close()
log.WithError(err).Debug("Disconnected from dmsg network.")
fmt.Printf("\n")
}
req.Header.Add("Cache-Control", "no-cache")
//check for errors in the response
res, err := client.Do(req)
if err != nil {
return nil
}
if res.Body != nil {
defer res.Body.Close() //nolint
}
body, err := io.ReadAll(res.Body)
if err != nil {
return nil
}
//fill in IPSkycoin struct with the response
err = json.Unmarshal(body, &ipskycoin)
if err != nil {
return nil
log.WithField("public_key", pk.String()).WithField("dmsg_disc", dmsgDisc).
Debug("Connecting to dmsg network...")

select {
case <-ctx.Done():
stop()
return nil, nil, ctx.Err()

case <-dmsgC.Ready():
log.Debug("Dmsg network ready.")
return dmsgC, stop, nil
}
return ipskycoin
}

var (
Expand Down
15 changes: 10 additions & 5 deletions pkg/visor/visorconfig/values_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ type Survey struct {
SkycoinAddress string `json:"skycoin_address,omitempty"`
GOOS string `json:"go_os,omitempty"`
GOARCH string `json:"go_arch,omitempty"`
IPInfo *IPSkycoin `json:"ip.skycoin.com,omitempty"`
IPAddr *IPAddr `json:"ip_addr,omitempty"`
IPAddr string `json:"ip_address,omitempty"`
Disks *ghw.BlockInfo `json:"ghw_blockinfo,omitempty"`
UUID uuid.UUID `json:"uuid,omitempty"`
SkywireVersion string `json:"skywire_version,omitempty"`
Expand All @@ -42,14 +41,20 @@ type Survey struct {
}

// SystemSurvey returns system survey
func SystemSurvey() (Survey, error) {
func SystemSurvey(dmsgDisc string) (Survey, error) {
disks, err := ghw.Block(ghw.WithDisableWarnings())
if err != nil {
return Survey{}, err
}
var ipAddr string
for {
ipAddr, err = FetchIP(dmsgDisc)
if err == nil {
break
}
}
s := Survey{
IPInfo: IPSkycoinFetch(),
IPAddr: IPA(),
IPAddr: ipAddr,
GOOS: runtime.GOOS,
GOARCH: runtime.GOARCH,
UUID: uuid.New(),
Expand Down
13 changes: 6 additions & 7 deletions pkg/visor/visorconfig/values_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ type Survey struct {
GOOS string `json:"go_os,omitempty"`
GOARCH string `json:"go_arch,omitempty"`
SYSINFO sysinfo.SysInfo `json:"zcalusic_sysinfo,omitempty"`
IPInfo *IPSkycoin `json:"ip.skycoin.com,omitempty"`
IPAddr *IPAddr `json:"ip_addr,omitempty"`
IPAddr string `json:"ip_address,omitempty"`
Disks *ghw.BlockInfo `json:"ghw_blockinfo,omitempty"`
Product *ghw.ProductInfo `json:"ghw_productinfo,omitempty"`
Memory *ghw.MemoryInfo `json:"ghw_memoryinfo,omitempty"`
Expand All @@ -49,7 +48,7 @@ type Survey struct {
}

// SystemSurvey returns system survey
func SystemSurvey() (Survey, error) {
func SystemSurvey(dmsgDisc string) (Survey, error) {
var si sysinfo.SysInfo
si.GetSysInfo()
disks, err := ghw.Block(ghw.WithDisableWarnings())
Expand All @@ -64,16 +63,16 @@ func SystemSurvey() (Survey, error) {
if err != nil && !strings.Contains(err.Error(), "Could not determine total usable bytes of memory") {
return Survey{}, err
}
var ipAddr string
for {
ipInfo := IPSkycoinFetch()
if ipInfo != nil {
ipAddr, err = FetchIP(dmsgDisc)
if err == nil {
break
}
}
s := Survey{
Timestamp: time.Now(),
IPInfo: IPSkycoinFetch(),
IPAddr: IPA(),
IPAddr: ipAddr,
GOOS: runtime.GOOS,
GOARCH: runtime.GOARCH,
SYSINFO: si,
Expand Down
15 changes: 11 additions & 4 deletions pkg/visor/visorconfig/values_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ type Survey struct {
SkycoinAddress string `json:"skycoin_address,omitempty"`
GOOS string `json:"go_os,omitempty"`
GOARCH string `json:"go_arch,omitempty"`
IPInfo *IPSkycoin `json:"ip.skycoin.com,omitempty"`
IPAddr *IPAddr `json:"ip_addr,omitempty"`
IPAddr string `json:"ip_address,omitempty"`
Disks *ghw.BlockInfo `json:"ghw_blockinfo,omitempty"`
Product *ghw.ProductInfo `json:"ghw_productinfo,omitempty"`
Memory *ghw.MemoryInfo `json:"ghw_memoryinfo,omitempty"`
Expand All @@ -44,7 +43,7 @@ type Survey struct {
}

// SystemSurvey returns system survey
func SystemSurvey() (Survey, error) {
func SystemSurvey(dmsgDisc string) (Survey, error) {
disks, err := ghw.Block(ghw.WithDisableWarnings())
if err != nil {
return Survey{}, err
Expand All @@ -57,8 +56,16 @@ func SystemSurvey() (Survey, error) {
if err != nil {
return Survey{}, err
}
var ipAddr string
for {
ipAddr, err = FetchIP(dmsgDisc)
if err == nil {
break
}
}

s := Survey{
IPInfo: IPSkycoinFetch(),
IPAddr: ipAddr,
GOOS: runtime.GOOS,
GOARCH: runtime.GOARCH,
UUID: uuid.New(),
Expand Down
Loading

0 comments on commit 99de0a1

Please sign in to comment.