-
Notifications
You must be signed in to change notification settings - Fork 32
/
Copy pathsb.go
110 lines (94 loc) · 2.27 KB
/
sb.go
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package main
import (
"context"
"log"
"os"
"path/filepath"
runtimeDebug "runtime/debug"
"github.com/tidwall/jsonc"
"github.com/pkg/errors"
box "github.com/sagernet/sing-box"
_ "github.com/sagernet/sing-box/include"
"github.com/sagernet/sing-box/option"
)
type SingBox struct {
Running bool
ConfPath string
instance *box.Box
cancel context.CancelFunc
}
func (s *SingBox) Close() {
if s.instance != nil {
_ = s.instance.Close()
}
if s.cancel != nil {
s.cancel()
}
s.Running = false
}
func (s *SingBox) Start(basePath, configPath string) error {
defer func() {
if err := recover(); err != nil {
log.Println(err)
}
}()
instance, cancel, err := create(filepath.Join(basePath, configPath))
if err != nil {
return err
}
runtimeDebug.FreeOSMemory()
s.Running = true
s.instance = instance
s.cancel = cancel
return nil
}
func create(configPath string) (*box.Box, context.CancelFunc, error) {
options, err := readConfig(configPath)
if err != nil {
return nil, nil, err
}
options.Experimental.ClashAPI.ExternalUI = filepath.Join(ConfDir, "ui")
options.Log.DisableColor = true
//options.Log.Output = filepath.Join(ConfDir, "singbox.log")
ctx, cancel := context.WithCancel(context.Background())
instance, err := box.New(box.Options{
Options: options,
Context: ctx,
PlatformInterface: nil,
})
if err != nil {
cancel()
return nil, nil, errors.Wrap(err, "sing-box core create service")
}
err = instance.Start()
if err != nil {
cancel()
return nil, nil, errors.Wrap(err, "sing-box core start service")
}
return instance, cancel, nil
}
func readConfig(configPath string) (option.Options, error) {
var (
configContent []byte
err error
)
configContent, err = os.ReadFile(configPath)
if err != nil {
return option.Options{}, errors.Wrap(err, "read config")
}
var options option.Options
err = options.UnmarshalJSON(jsonc.ToJSON(configContent))
if err != nil {
return option.Options{}, errors.Wrap(err, "decode config")
}
if options.Log == nil {
options.Log = &option.LogOptions{}
}
if options.Experimental == nil {
options.Experimental = &option.ExperimentalOptions{}
}
if options.Experimental.ClashAPI == nil {
options.Experimental.ClashAPI = &option.ClashAPIOptions{}
}
return options, nil
}