Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid header field value for "X-Lantern-Device-Id" #1285

Merged
merged 26 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions android/.settings/org.eclipse.buildship.core.prefs

This file was deleted.

115 changes: 68 additions & 47 deletions desktop/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"net"
"net/http"
"os"
"path/filepath"
"sync"
"sync/atomic"
"time"
Expand All @@ -34,7 +35,6 @@

"github.com/getlantern/lantern-client/desktop/autoupdate"
"github.com/getlantern/lantern-client/desktop/datacap"
"github.com/getlantern/lantern-client/desktop/settings"
"github.com/getlantern/lantern-client/desktop/ws"
"github.com/getlantern/lantern-client/internalsdk/auth"
"github.com/getlantern/lantern-client/internalsdk/common"
Expand All @@ -43,7 +43,7 @@
)

var (
log = golog.LoggerFor("lantern-desktop.app")
log = golog.LoggerFor("lantern-client.app")
startTime = time.Now()
)

Expand All @@ -53,63 +53,80 @@

}

// App is the core of the Lantern desktop application, in the form of a library.
// App is the core of the Lantern desktop application, managing components and configurations.
type App struct {
hasExited atomic.Bool
fetchedGlobalConfig atomic.Bool
fetchedProxiesConfig atomic.Bool
hasSucceedingProxy atomic.Bool

Flags flashlight.Flags
configDir string
exited eventual.Value
settings *settings.Settings
hasExited atomic.Bool // Tracks if the app has exited.
fetchedGlobalConfig atomic.Bool // Indicates if the global configuration was fetched.
fetchedProxiesConfig atomic.Bool // Tracks whether the proxy configuration was fetched.
hasSucceedingProxy atomic.Bool // Tracks if a succeeding proxy is available.

Flags flashlight.Flags // Command-line flags passed to the app.
configDir string // Directory for storing configuration files.
exited eventual.Value // Signals when the app has exited.
settings *Settings // User settings for the application.
configService *configService
statsTracker *statsTracker

muExitFuncs sync.RWMutex
exitFuncs []func()

translations eventual.Value
translations eventual.Value // Translation files for localization.
flashlight *flashlight.Flashlight // Flashlight library for networking and proxying.

flashlight *flashlight.Flashlight

authClient auth.AuthClient
proClient proclient.ProClient

selectedTab Tab

connectionStatusCallbacks []func(isConnected bool)
authClient auth.AuthClient // Client for managing authentication.
proClient proclient.ProClient // Client for managing interaction with the Pro server.

selectedTab Tab // Tracks the currently selected UI tab.
connectionStatusCallbacks []func(isConnected bool) // Listeners for connection status changes.
// Websocket-related settings
websocketAddr string
ws ws.UIChannel

cachedUserData sync.Map

onUserData []func(current *protos.User, new *protos.User)
websocketAddr string // Address for WebSocket connections.
ws ws.UIChannel // UI channel for WebSocket communication.
cachedUserData sync.Map // Cached user data.
onUserData []func(current *protos.User, new *protos.User) // Listeners for user data changes.

mu sync.RWMutex
}

// NewApp creates a new desktop app that initializes the app and acts as a moderator between all desktop components.
func NewApp() (*App, error) {
// initialize app config and flags based on environment variables
flags, err := initializeAppConfig()
if err != nil {
return nil, fmt.Errorf("failed to initialize app config: %w", err)
flags := flashlight.ParseFlags()
if flags.Pprof {
go startPprof("localhost:6060")
}

// helper to resolve CONFIG_DIR to an absolute path
resolveConfigDir := func(dir string) string {
if filepath.IsAbs(dir) {
return dir
}
absPath, err := filepath.Abs(dir)
if err != nil {
return dir
}
return absPath
}

configDir := resolveConfigDir(flags.ConfigDir)

if err := createDirIfNotExists(configDir, defaultConfigDirPerm); err != nil {
return nil, fmt.Errorf("unable to create config directory %s: %v", configDir, err)
}
flags.ConfigDir = configDir

log.Debugf("Config directory %s sticky %v readable %v", configDir, flags.StickyConfig, flags.ReadableConfig)
return NewAppWithFlags(flags, flags.ConfigDir)
}

// NewAppWithFlags creates a new instance of App initialized with the given flags and configDir
// NewAppWithFlags creates a new App instance with the given flags and configuration directory.
func NewAppWithFlags(flags flashlight.Flags, configDir string) (*App, error) {
if configDir == "" {
log.Debug("Config directory is empty, using default location")
configDir = appdir.General(common.DefaultAppName)
}
ss := settings.LoadSettings(configDir)
// Load settings and initialize trackers and services.
ss := LoadSettings(configDir)
statsTracker := NewStatsTracker()

app := &App{
Flags: flags,
configDir: configDir,
Expand All @@ -123,6 +140,7 @@
ws: ws.NewUIChannel(),
}

// Start the WebSocket server for UI communication.
if err := app.serveWebsocket(); err != nil {
log.Error(err)
}
Expand All @@ -147,7 +165,7 @@
return app, nil
}

// Run starts the app.
// Run starts the application and initializes necessary components.
func (app *App) Run(ctx context.Context) {
golog.OnFatal(app.exitOnFatal)
go func() {
Expand All @@ -157,11 +175,8 @@
}()

log.Debug(app.Flags)
userConfig := func() common.UserConfig {
return settings.UserConfig(app.Settings())
}
proClient := proclient.NewClient(fmt.Sprintf("https://%s", common.ProAPIHost), userConfig)
authClient := auth.NewClient(fmt.Sprintf("https://%s", common.DFBaseUrl), userConfig)
proClient := proclient.NewClient(fmt.Sprintf("https://%s", common.ProAPIHost), app.UserConfig)
authClient := auth.NewClient(fmt.Sprintf("https://%s", common.DFBaseUrl), app.UserConfig)

app.mu.Lock()
app.proClient = proClient
Expand All @@ -170,11 +185,12 @@

settings := app.Settings()

// Check and apply the ProxyAll flag.
if app.Flags.ProxyAll {
// If proxyall flag was supplied, force proxying of all
settings.SetProxyAll(true)
}

// Determine the listen address for local HTTP and SOCKS proxies
listenAddr := app.Flags.Addr
if listenAddr == "" {
listenAddr = settings.GetAddr()
Expand All @@ -200,6 +216,7 @@
}()
}
var err error
// Initialize flashlight
app.flashlight, err = flashlight.New(
common.DefaultAppName,
common.ApplicationVersion,
Expand All @@ -216,8 +233,7 @@
app.IsPro,
settings.GetLanguage,
func(addr string) (string, error) { return addr, nil }, // no dnsgrab reverse lookups on desktop
// Dummy analytics function
func(category, action, label string) {},
func(category, action, label string) {}, // Dummy analytics function
flashlight.WithOnConfig(app.onConfigUpdate),
flashlight.WithOnProxies(app.onProxiesUpdate),
flashlight.WithOnSucceedingProxy(app.onSucceedingProxy),
Expand All @@ -236,6 +252,11 @@
)
}

// UserConfig returns the current user configuration after applying settings.
func (app *App) UserConfig() common.UserConfig {
return userConfig(app.Settings())
}

// IsFeatureEnabled checks whether or not the given feature is enabled by flashlight
func (app *App) IsFeatureEnabled(feature string) bool {
if app.flashlight == nil {
Expand Down Expand Up @@ -281,7 +302,7 @@
}

isProUser := func() (bool, bool) {
return app.IsProUser(context.Background(), settings.UserConfig(app.Settings()))
return app.IsProUser(context.Background(), app.userConfig())

Check failure on line 305 in desktop/app/app.go

View workflow job for this annotation

GitHub Actions / build

app.userConfig undefined (type *App has no field or method userConfig, but does have method UserConfig)
}

if err := app.statsTracker.StartService(app.ws); err != nil {
Expand Down Expand Up @@ -364,7 +385,7 @@

// OnSettingChange sets a callback cb to get called when attr is changed from server.
// When calling multiple times for same attr, only the last one takes effect.
func (app *App) OnSettingChange(attr settings.SettingName, cb func(interface{})) {
func (app *App) OnSettingChange(attr SettingName, cb func(interface{})) {
app.settings.OnChange(attr, cb)
}

Expand All @@ -382,7 +403,7 @@
}
go app.fetchDeviceLinkingCode(ctx)

app.OnSettingChange(settings.SNSystemProxy, func(val interface{}) {
app.OnSettingChange(SNSystemProxy, func(val interface{}) {
enable := val.(bool)
if enable {
app.SysproxyOn()
Expand Down Expand Up @@ -562,7 +583,7 @@

// IsPro indicates whether or not the app is pro
func (app *App) IsPro() bool {
isPro, _ := app.IsProUserFast(settings.UserConfig(app.Settings()))
isPro, _ := app.IsProUserFast(userConfig(app.Settings()))
return isPro
}

Expand Down Expand Up @@ -651,7 +672,7 @@
return io.ReadAll(f)
}

func (app *App) Settings() *settings.Settings {
func (app *App) Settings() *Settings {
app.mu.RLock()
defer app.mu.RUnlock()
return app.settings
Expand Down
53 changes: 0 additions & 53 deletions desktop/app/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,10 @@ package app
import (
"context"
"encoding/json"
"fmt"
"os"
"path/filepath"
"strconv"
"sync"

"github.com/getlantern/appdir"
"github.com/getlantern/flashlight/v7"
fcommon "github.com/getlantern/flashlight/v7/common"
"github.com/getlantern/flashlight/v7/config"
"github.com/getlantern/lantern-client/desktop/ws"
Expand Down Expand Up @@ -115,52 +111,3 @@ func (app *App) sendConfigOptions() {
},
})
}

// initializeAppConfig initializes application configuration and flags based on environment variables
func initializeAppConfig() (flashlight.Flags, error) {
flags := flashlight.ParseFlags()
if flags.Pprof {
go startPprof("localhost:6060")
}
parseBoolEnv := func(key string, defaultValue bool) bool {
val := os.Getenv(key)
parsedValue, err := strconv.ParseBool(val)
if err != nil {
return defaultValue
}
return parsedValue
}

// helper to resolve CONFIG_DIR to an absolute path
resolveConfigDir := func(dir string) string {
if filepath.IsAbs(dir) {
return dir
}
absPath, err := filepath.Abs(dir)
if err != nil {
return dir
}
return absPath
}

// Parse environment-based flags
stickyConfig := parseBoolEnv("STICKY_CONFIG", false)
readableConfig := parseBoolEnv("READABLE_CONFIG", true)
configDir := os.Getenv("CONFIG_DIR")
if configDir == "" {
configDir = appdir.General(common.DefaultAppName)
log.Debugf("CONFIG_DIR not set. Using default: %s", configDir)
} else {
configDir = resolveConfigDir(configDir)
}
if err := createDirIfNotExists(configDir, defaultConfigDirPerm); err != nil {
return flags, fmt.Errorf("unable to create config directory %s: %v", configDir, err)
}
flags.StickyConfig = stickyConfig
flags.ReadableConfig = readableConfig
flags.ConfigDir = configDir

log.Debugf("Config options: directory %v sticky %v readable %v", configDir,
stickyConfig, readableConfig)
return flags, nil
}
3 changes: 1 addition & 2 deletions desktop/app/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import (
"github.com/getlantern/flashlight/v7/integrationtest"
"github.com/getlantern/flashlight/v7/logging"
"github.com/getlantern/lantern-client/desktop/doh"
"github.com/getlantern/lantern-client/desktop/settings"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -189,7 +188,7 @@ func startApp(t *testing.T, helper *integrationtest.Helper) (*App, error) {
UIAddr: "127.0.0.1:16823",
Timeout: time.Duration(0),
}
ss := settings.EmptySettings()
ss := emptySettings()
a, err := NewAppWithFlags(flags, helper.ConfigDir)
require.NoError(t, err)
id := ss.GetUserID()
Expand Down
5 changes: 2 additions & 3 deletions desktop/app/loconfscanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (

"github.com/getlantern/lantern-client/desktop/loconf"
"github.com/getlantern/lantern-client/desktop/notifier"
"github.com/getlantern/lantern-client/desktop/settings"
)

// LoconfScanner starts a goroutine to periodically check for new loconf files.
Expand All @@ -28,7 +27,7 @@ import (
// show the announcement or not).
//
// Returns a function to stop the loop.
func LoconfScanner(settings *settings.Settings, configDir string, interval time.Duration, proChecker func() (bool, bool), iconURL func() string) (stop func()) {
func LoconfScanner(settings *Settings, configDir string, interval time.Duration, proChecker func() (bool, bool), iconURL func() string) (stop func()) {
loc := &loconfer{
log: golog.LoggerFor("loconfer"),
configDir: configDir,
Expand Down Expand Up @@ -87,7 +86,7 @@ type loconfer struct {
configDir string
r *rand.Rand
iconURL func() string
settings *settings.Settings
settings *Settings
}

func (loc *loconfer) onLoconf(lc *loconf.LoConf, isPro bool) {
Expand Down
File renamed without changes.
Loading
Loading