diff --git a/desktop/app/app.go b/desktop/app/app.go index 1a66672e0..61643ef3e 100644 --- a/desktop/app/app.go +++ b/desktop/app/app.go @@ -9,7 +9,6 @@ import ( "net" "net/http" "os" - "strings" "sync" "sync/atomic" "time" @@ -39,16 +38,14 @@ import ( "github.com/getlantern/lantern-client/desktop/ws" "github.com/getlantern/lantern-client/internalsdk/auth" "github.com/getlantern/lantern-client/internalsdk/common" - "github.com/getlantern/lantern-client/internalsdk/pro" proclient "github.com/getlantern/lantern-client/internalsdk/pro" "github.com/getlantern/lantern-client/internalsdk/protos" "github.com/getlantern/lantern-client/internalsdk/webclient" ) var ( - log = golog.LoggerFor("lantern-desktop.app") - startTime = time.Now() - translationAppName = strings.ToUpper(common.DefaultAppName) + log = golog.LoggerFor("lantern-desktop.app") + startTime = time.Now() ) func init() { @@ -78,18 +75,16 @@ type App struct { flashlight *flashlight.Flashlight - issueReporter *issueReporter - authClient auth.AuthClient - proClient proclient.ProClient + authClient auth.AuthClient + proClient proclient.ProClient selectedTab Tab connectionStatusCallbacks []func(isConnected bool) // Websocket-related settings - websocketAddr string - websocketServer *http.Server - ws ws.UIChannel + websocketAddr string + ws ws.UIChannel cachedUserData sync.Map plansCache sync.Map @@ -145,9 +140,12 @@ func NewAppWithFlags(flags flashlight.Flags, configDir string) *App { log.Debugf("Using configdir: %v", configDir) - app.issueReporter = newIssueReporter(app) app.translations.Set(os.DirFS("locale/translation")) + if e := app.configService.StartService(app.ws); e != nil { + app.Exit(fmt.Errorf("unable to register config service: %q", e)) + } + return app } @@ -169,7 +167,6 @@ func (app *App) Run(ctx context.Context) { } proClient := proclient.NewClient(fmt.Sprintf("https://%s", common.ProAPIHost), &webclient.Opts{ UserConfig: userConfig, - }) authClient := auth.NewClient(fmt.Sprintf("https://%s", common.DFBaseUrl), userConfig) @@ -230,6 +227,7 @@ func (app *App) Run(ctx context.Context) { func(category, action, label string) {}, flashlight.WithOnConfig(app.onConfigUpdate), flashlight.WithOnProxies(app.onProxiesUpdate), + flashlight.WithOnSucceedingProxy(app.onSucceedingProxy), ) if err != nil { app.Exit(err) @@ -285,11 +283,6 @@ func (app *App) beforeStart(ctx context.Context, listenAddr string) { os.Exit(0) } - if e := app.configService.StartService(app.ws); e != nil { - app.Exit(fmt.Errorf("unable to register config service: %q", e)) - return - } - if e := app.settings.StartService(app.ws); e != nil { app.Exit(fmt.Errorf("unable to register settings service: %q", e)) return @@ -443,13 +436,12 @@ func (app *App) onConfigUpdate(cfg *config.Global, src config.Source) { func (app *App) onProxiesUpdate(proxies []dialer.ProxyDialer, src config.Source) { log.Debugf("[Startup Desktop] Got proxies update from %v", src) app.fetchedProxiesConfig.Store(true) - app.hasSucceedingProxy.Store(true) app.sendConfigOptions() } -func (app *App) onSucceedingProxy(succeeding bool) { - app.hasSucceedingProxy.Store(succeeding) - log.Debugf("[Startup Desktop] onSucceedingProxy %v", succeeding) +func (app *App) onSucceedingProxy() { + app.hasSucceedingProxy.Store(true) + log.Debugf("[Startup Desktop] onSucceedingProxy") } // HasSucceedingProxy returns whether or not the app is currently configured with any succeeding proxies @@ -672,12 +664,13 @@ func (app *App) FetchPaymentMethods(ctx context.Context) (*proclient.PaymentMeth if !ok { return nil, errors.New("No desktop payment providers found") } - for _, paymentMethod := range desktopPaymentMethods { - for i, provider := range paymentMethod.Providers { + for i := range desktopPaymentMethods { + paymentMethod := &desktopPaymentMethods[i] + for j, provider := range paymentMethod.Providers { if resp.Logo[provider.Name] != nil { logos := resp.Logo[provider.Name].([]interface{}) for _, logo := range logos { - paymentMethod.Providers[i].LogoUrls = append(paymentMethod.Providers[i].LogoUrls, logo.(string)) + paymentMethod.Providers[j].LogoUrls = append(paymentMethod.Providers[j].LogoUrls, logo.(string)) } } } @@ -812,7 +805,7 @@ func (app *App) AuthClient() auth.AuthClient { return app.authClient } -func (app *App) ProClient() pro.ProClient { +func (app *App) ProClient() proclient.ProClient { app.mu.RLock() defer app.mu.RUnlock() return app.proClient diff --git a/desktop/app/config.go b/desktop/app/config.go index 5dbcbafbf..9e2363ae4 100644 --- a/desktop/app/config.go +++ b/desktop/app/config.go @@ -61,7 +61,7 @@ func (s *configService) StartService(channel ws.UIChannel) (err error) { return err } -func (s *configService) sendConfigOptions(cfg ConfigOptions) { +func (s *configService) sendConfigOptions(cfg *ConfigOptions) { b, _ := json.Marshal(&cfg) log.Debugf("Sending config options to client %s", string(b)) s.service.Out <- cfg @@ -90,7 +90,7 @@ func (app *App) sendConfigOptions() { log.Debugf("DEBUG: Devices: %s", string(devices)) log.Debugf("Expiration date: %s", app.settings.GetExpirationDate()) - app.configService.sendConfigOptions(ConfigOptions{ + app.configService.sendConfigOptions(&ConfigOptions{ DevelopmentMode: common.IsDevEnvironment(), AppVersion: common.ApplicationVersion, ReplicaAddr: "", @@ -154,7 +154,7 @@ func initializeAppConfig() (flashlight.Flags, error) { configDir = resolveConfigDir(configDir) } if err := createDirIfNotExists(configDir, defaultConfigDirPerm); err != nil { - return flags, fmt.Errorf("Unable to create config directory %s: %v", configDir, err) + return flags, fmt.Errorf("unable to create config directory %s: %v", configDir, err) } flags.StickyConfig = stickyConfig flags.ReadableConfig = readableConfig diff --git a/desktop/app/defaults.go b/desktop/app/defaults.go index f4d874c1d..015f21dfd 100644 --- a/desktop/app/defaults.go +++ b/desktop/app/defaults.go @@ -3,34 +3,7 @@ package app -import ( - "crypto/rand" - "encoding/hex" - - "github.com/getlantern/lantern-client/desktop/settings" -) - const ( defaultHTTPProxyAddress = "127.0.0.1:0" defaultSOCKSProxyAddress = "127.0.0.1:0" ) - -func randRead(size int) string { - buf := make([]byte, size) - if _, err := rand.Read(buf); err != nil { - log.Fatalf("Failed to get random bytes: %s", err) - } - return hex.EncodeToString(buf) -} - -// localHTTPToken fetches the local HTTP token from disk if it's there, and -// otherwise creates a new one and stores it. -func localHTTPToken(set *settings.Settings) string { - tok := set.GetLocalHTTPToken() - if tok == "" { - t := randRead(16) - set.SetLocalHTTPToken(t) - return t - } - return tok -} diff --git a/desktop/app/fronted_test.go b/desktop/app/fronted_test.go deleted file mode 100644 index 964d59868..000000000 --- a/desktop/app/fronted_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package app - -import ( - "os" - "path/filepath" - "time" - - "github.com/getlantern/flashlight/v7/config" - "github.com/getlantern/flashlight/v7/embeddedconfig" - "github.com/getlantern/flashlight/v7/geolookup" - "github.com/getlantern/fronted" - "github.com/getlantern/yaml" -) - -func configureFronted() { - tempConfigDir, err := os.MkdirTemp("", "tmp_config") - if err != nil { - log.Errorf("Unable to create temp config dir: %v", err) - os.Exit(1) - } - defer os.RemoveAll(tempConfigDir) - - cfg := config.NewGlobal() - err = yaml.Unmarshal(embeddedconfig.Global, cfg) - if err != nil { - log.Errorf("Unable to unmarshal embedded global config: %v", err) - os.Exit(1) - } - certs, err := cfg.TrustedCACerts() - if err != nil { - log.Errorf("Unable to read trusted certs: %v", err) - } - log.Debug(cfg.Client.FrontedProviders()) - fronted.Configure(certs, cfg.Client.FrontedProviders(), config.DefaultFrontedProviderID, filepath.Join(tempConfigDir, "masquerade_cache")) - - // Perform initial geolookup with a high timeout so that we don't later timeout when trying to - geolookup.GetCountry(5 * time.Second) -} diff --git a/desktop/app/issue.go b/desktop/app/issue.go deleted file mode 100644 index 3473f8340..000000000 --- a/desktop/app/issue.go +++ /dev/null @@ -1,121 +0,0 @@ -package app - -import ( - "math" - "strconv" - - "github.com/getlantern/lantern-client/desktop/settings" - "github.com/getlantern/lantern-client/internalsdk/common" - "github.com/getlantern/lantern-client/internalsdk/pro" - - "github.com/getlantern/flashlight/v7/issue" - "github.com/getlantern/flashlight/v7/util" - "github.com/getlantern/osversion" -) - -var ( - // Number of runes(code points - characters of variable length bytes depending on encoding) - // allowed in fileName length - maxNameLength uint = 60 - // Number of bytes allowed in file attachment (8 mb) - maxFileSize float64 = 8 * math.Pow(10, 6) -) - -type issueReporter struct { - settings *settings.Settings - proClient pro.ProClient -} - -type issueMessage struct { - Email string `json:"email,omitempty"` - IssueType string `json:"issueType,omitempty"` - Note string `json:"note,omitempty"` - File string `json:"file,omitempty"` - FileName string `json:"fileName,omitempty"` - // If true, diagnostics will be run and a report will be attached - RunDiagnostics bool `json:"runDiagnostics,omitempty"` - // DiagnosticsYAML is a YAML-encoded diagnostics report. - DiagnosticsYAML []byte - // ProxyCapture is a gzipped pcapng file related to diagnostics. - ProxyCapture []byte -} - -// newIssueReporter creates a new issue reporter that can be used to send issue reports -// to the Lantern team. -func newIssueReporter(app *App) *issueReporter { - return &issueReporter{ - proClient: app.proClient, - settings: app.settings, - } -} - -// sendIssueReport creates an issue report from the given UI message and submits it to -// lantern-cloud/issue service, which is then forwarded to the ticket system via API -func (reporter *issueReporter) sendIssueReport(msg *issueMessage) error { - settings := reporter.settings - uc := common.NewUserConfig( - common.DefaultAppName, - settings.GetDeviceID(), - settings.GetUserID(), - settings.GetToken(), - nil, - settings.GetLanguage(), - ) - - issueTypeInt, err := strconv.Atoi(msg.IssueType) - if err != nil { - return err - } - subscriptionLevel := "free" - if settings.IsProUser() { - subscriptionLevel = "pro" - } - var osVersion string - osVersion, err = osversion.GetHumanReadable() - if err != nil { - log.Errorf("Unable to get version: %v", err) - } - attachments := []*issue.Attachment{} - // Include screenshot if the user attached it to the report - fileContent, fileName := msg.File, msg.FileName - if fileContent != "" && fileName != "" { - fileName = util.TrimStringAsRunes(maxNameLength, fileName, true) - fileName = util.SanitizePathString(fileName) - - byteLen := float64(len(fileContent)) - if byteLen <= maxFileSize { - attachments = append(attachments, &issue.Attachment{ - Data: []byte(fileContent), - Name: fileName, - }) - } else { - log.Errorf("file %s too large", fileName) - } - } - - if msg.DiagnosticsYAML != nil { - attachments = append(attachments, &issue.Attachment{ - Name: "diagnostics.yaml", - Data: msg.DiagnosticsYAML, - }) - } - if msg.ProxyCapture != nil { - attachments = append(attachments, &issue.Attachment{ - Name: "proxy_capture.zip", - Data: msg.ProxyCapture, - }) - } - - return issue.SendReport( - uc, - issueTypeInt, - msg.Note, - subscriptionLevel, - msg.Email, - common.ApplicationVersion, - "", - "", - osVersion, - attachments, - ) -} diff --git a/desktop/app/sysproxy.go b/desktop/app/sysproxy.go index 54e607177..f8099a389 100644 --- a/desktop/app/sysproxy.go +++ b/desktop/app/sysproxy.go @@ -61,7 +61,7 @@ func (app *App) SysProxyOff() error { log.Debug("Force clearing system proxy directly, just in case") addr, found := getProxyAddr() if !found { - err := fmt.Errorf("Unable to find proxy address, can't force clear system proxy") + err := fmt.Errorf("unable to find proxy address, can't force clear system proxy") op.FailIf(log.Error(err)) return err } diff --git a/desktop/app/ws.go b/desktop/app/ws.go index acdb5c4b0..d84c9a164 100644 --- a/desktop/app/ws.go +++ b/desktop/app/ws.go @@ -42,9 +42,3 @@ func (app *App) WebsocketAddr() string { } return app.websocketAddr } - -func (app *App) setWebsocketServer(server *http.Server) { - app.mu.Lock() - defer app.mu.Unlock() - app.websocketServer = server -}