1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
package main
import (
"embed"
"flag"
"log"
"os"
"path/filepath"
"runtime"
"github.com/wailsapp/wails/v2"
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
//go:embed frontend/dist
var assets embed.FS
func main() {
apiURL := flag.String("api", "https://vpn.em-sysadmin.xyz", "API server URL")
dataDir := flag.String("data", defaultDataDir(), "data directory")
flag.Parse()
// Ensure data dir exists
os.MkdirAll(*dataDir, 0o755)
// Setup file logging so we always have diagnostics
logPath := filepath.Join(*dataDir, "vpnem.log")
logFile, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o644)
if err == nil {
log.SetOutput(logFile)
defer logFile.Close()
}
log.Printf("vpnem starting, data=%s, api=%s, os=%s", *dataDir, *apiURL, runtime.GOOS)
// Kill previous instances of vpnem and sing-box
killPrevious()
// Check wintun.dll on Windows
if runtime.GOOS == "windows" {
exe, _ := os.Executable()
exeDir := filepath.Dir(exe)
wintunPaths := []string{
filepath.Join(exeDir, "wintun.dll"),
filepath.Join(*dataDir, "wintun.dll"),
"wintun.dll",
}
found := false
for _, p := range wintunPaths {
if _, err := os.Stat(p); err == nil {
log.Printf("wintun.dll found: %s", p)
found = true
break
}
}
if !found {
log.Printf("WARNING: wintun.dll not found! TUN will fail. Searched: %v", wintunPaths)
}
}
app := NewApp(*dataDir, *apiURL)
log.Println("starting Wails UI")
if err := wails.Run(&options.App{
Title: "vpnem",
Width: 480,
Height: 600,
MinWidth: 400,
MinHeight: 500,
AssetServer: &assetserver.Options{
Assets: assets,
},
OnStartup: app.startup,
OnShutdown: app.shutdown,
Bind: []interface{}{
app,
},
}); err != nil {
log.Printf("FATAL wails error: %v", err)
// On Windows, also write to a visible error file
if runtime.GOOS == "windows" {
errPath := filepath.Join(*dataDir, "ERROR.txt")
os.WriteFile(errPath, []byte("vpnem failed to start:\n"+err.Error()+"\n\nCheck vpnem.log for details.\n"), 0o644)
}
os.Exit(1)
}
}
func defaultDataDir() string {
if runtime.GOOS == "windows" {
return `C:\ProgramData\vpnem`
}
home, _ := os.UserHomeDir()
return filepath.Join(home, ".local", "share", "vpnem")
}
|