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

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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.

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

"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 @@ import (
)

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

Expand All @@ -53,63 +53,75 @@ func init() {

}

// 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
configService *configService
statsTracker *statsTracker

muExitFuncs sync.RWMutex
exitFuncs []func()

translations eventual.Value

flashlight *flashlight.Flashlight

authClient auth.AuthClient
proClient proclient.ProClient

selectedTab Tab

connectionStatusCallbacks []func(isConnected bool)

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 // Translation files for localization.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we still using translations on the go end?

flashlight *flashlight.Flashlight // Flashlight library for networking and proxying.
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 the configuration directory 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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@atavism I think you missed this. We need this unless all files are created in the root of the repo folder.

       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 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 +135,7 @@ func NewAppWithFlags(flags flashlight.Flags, configDir string) (*App, error) {
ws: ws.NewUIChannel(),
}

// Start the WebSocket server for UI communication.
if err := app.serveWebsocket(); err != nil {
log.Error(err)
}
Expand All @@ -147,7 +160,7 @@ func NewAppWithFlags(flags flashlight.Flags, configDir string) (*App, error) {
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 +170,8 @@ func (app *App) Run(ctx context.Context) {
}()

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 +180,12 @@ func (app *App) Run(ctx context.Context) {

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 +211,7 @@ func (app *App) Run(ctx context.Context) {
}()
}
var err error
// Initialize flashlight
app.flashlight, err = flashlight.New(
common.DefaultAppName,
common.ApplicationVersion,
Expand All @@ -216,8 +228,7 @@ func (app *App) Run(ctx context.Context) {
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 +247,20 @@ func (app *App) Run(ctx context.Context) {
)
}

// UserConfig returns the current user configuration after applying settings.
func (app *App) UserConfig() common.UserConfig {
settings := app.Settings()
userID, deviceID, token := settings.GetUserID(), settings.GetDeviceID(), settings.GetToken()
return common.NewUserConfig(
common.DefaultAppName,
deviceID,
userID,
token,
nil,
settings.GetLanguage(),
)
}

// 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 +306,7 @@ func (app *App) beforeStart(ctx context.Context, listenAddr string) {
}

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

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

// 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 +407,7 @@ func (app *App) afterStart(cl *flashlightClient.Client) {
}
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 +587,7 @@ func (app *App) exitOnFatal(err error) {

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

Expand Down Expand Up @@ -651,7 +676,7 @@ func (app *App) GetTranslations(filename string) ([]byte, error) {
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