@@ -11,12 +11,11 @@ import (
1111 "strings"
1212
1313 cftls "github.com/sagernet/cloudflare-tls"
14+ "github.com/sagernet/fswatch"
1415 "github.com/sagernet/sing-box/log"
1516 "github.com/sagernet/sing-box/option"
1617 E "github.com/sagernet/sing/common/exceptions"
1718 "github.com/sagernet/sing/common/ntp"
18-
19- "github.com/fsnotify/fsnotify"
2019)
2120
2221type echServerConfig struct {
@@ -26,9 +25,8 @@ type echServerConfig struct {
2625 key []byte
2726 certificatePath string
2827 keyPath string
29- watcher * fsnotify.Watcher
3028 echKeyPath string
31- echWatcher * fsnotify .Watcher
29+ watcher * fswatch .Watcher
3230}
3331
3432func (c * echServerConfig ) ServerName () string {
@@ -66,159 +64,92 @@ func (c *echServerConfig) Clone() Config {
6664}
6765
6866func (c * echServerConfig ) Start () error {
69- if c .certificatePath != "" && c .keyPath != "" {
70- err := c .startWatcher ()
71- if err != nil {
72- c .logger .Warn ("create fsnotify watcher: " , err )
73- }
74- }
75- if c .echKeyPath != "" {
76- err := c .startECHWatcher ()
77- if err != nil {
78- c .logger .Warn ("create fsnotify watcher: " , err )
79- }
67+ err := c .startWatcher ()
68+ if err != nil {
69+ c .logger .Warn ("create credentials watcher: " , err )
8070 }
8171 return nil
8272}
8373
8474func (c * echServerConfig ) startWatcher () error {
85- watcher , err := fsnotify .NewWatcher ()
86- if err != nil {
87- return err
88- }
75+ var watchPath []string
8976 if c .certificatePath != "" {
90- err = watcher .Add (c .certificatePath )
91- if err != nil {
92- return err
93- }
77+ watchPath = append (watchPath , c .certificatePath )
9478 }
9579 if c .keyPath != "" {
96- err = watcher .Add (c .keyPath )
97- if err != nil {
98- return err
99- }
80+ watchPath = append (watchPath , c .keyPath )
81+ }
82+ if c .echKeyPath != "" {
83+ watchPath = append (watchPath , c .echKeyPath )
84+ }
85+ if len (watchPath ) == 0 {
86+ return nil
87+ }
88+ watcher , err := fswatch .NewWatcher (fswatch.Options {
89+ Path : watchPath ,
90+ Callback : func (path string ) {
91+ err := c .credentialsUpdated (path )
92+ if err != nil {
93+ c .logger .Error (E .Cause (err , "reload credentials from " , path ))
94+ }
95+ },
96+ })
97+ if err != nil {
98+ return err
10099 }
101100 c .watcher = watcher
102- go c .loopUpdate ()
103101 return nil
104102}
105103
106- func (c * echServerConfig ) loopUpdate () {
107- for {
108- select {
109- case event , ok := <- c .watcher .Events :
110- if ! ok {
111- return
112- }
113- if event .Op & fsnotify .Write != fsnotify .Write {
114- continue
115- }
116- err := c .reloadKeyPair ()
104+ func (c * echServerConfig ) credentialsUpdated (path string ) error {
105+ if path == c .certificatePath || path == c .keyPath {
106+ if path == c .certificatePath {
107+ certificate , err := os .ReadFile (c .certificatePath )
117108 if err != nil {
118- c . logger . Error ( E . Cause ( err , "reload TLS key pair" ))
109+ return err
119110 }
120- case err , ok := <- c .watcher .Errors :
121- if ! ok {
122- return
111+ c .certificate = certificate
112+ } else {
113+ key , err := os .ReadFile (c .keyPath )
114+ if err != nil {
115+ return err
123116 }
124- c .logger . Error ( E . Cause ( err , "fsnotify error" ))
117+ c .key = key
125118 }
126- }
127- }
128-
129- func (c * echServerConfig ) reloadKeyPair () error {
130- if c .certificatePath != "" {
131- certificate , err := os .ReadFile (c .certificatePath )
119+ keyPair , err := cftls .X509KeyPair (c .certificate , c .key )
132120 if err != nil {
133- return E .Cause (err , "reload certificate from " , c . certificatePath )
121+ return E .Cause (err , "parse key pair" )
134122 }
135- c .certificate = certificate
136- }
137- if c . keyPath != "" {
138- key , err := os .ReadFile (c .keyPath )
123+ c .config . Certificates = []cftls. Certificate { keyPair }
124+ c . logger . Info ( "reloaded TLS certificate" )
125+ } else {
126+ echKeyContent , err := os .ReadFile (c .echKeyPath )
139127 if err != nil {
140- return E . Cause ( err , "reload key from " , c . keyPath )
128+ return err
141129 }
142- c .key = key
143- }
144- keyPair , err := cftls .X509KeyPair (c .certificate , c .key )
145- if err != nil {
146- return E .Cause (err , "reload key pair" )
147- }
148- c .config .Certificates = []cftls.Certificate {keyPair }
149- c .logger .Info ("reloaded TLS certificate" )
150- return nil
151- }
152-
153- func (c * echServerConfig ) startECHWatcher () error {
154- watcher , err := fsnotify .NewWatcher ()
155- if err != nil {
156- return err
157- }
158- err = watcher .Add (c .echKeyPath )
159- if err != nil {
160- return err
161- }
162- c .echWatcher = watcher
163- go c .loopECHUpdate ()
164- return nil
165- }
166-
167- func (c * echServerConfig ) loopECHUpdate () {
168- for {
169- select {
170- case event , ok := <- c .echWatcher .Events :
171- if ! ok {
172- return
173- }
174- if event .Op & fsnotify .Write != fsnotify .Write {
175- continue
176- }
177- err := c .reloadECHKey ()
178- if err != nil {
179- c .logger .Error (E .Cause (err , "reload ECH key" ))
180- }
181- case err , ok := <- c .echWatcher .Errors :
182- if ! ok {
183- return
184- }
185- c .logger .Error (E .Cause (err , "fsnotify error" ))
130+ block , rest := pem .Decode (echKeyContent )
131+ if block == nil || block .Type != "ECH KEYS" || len (rest ) > 0 {
132+ return E .New ("invalid ECH keys pem" )
186133 }
134+ echKeys , err := cftls .EXP_UnmarshalECHKeys (block .Bytes )
135+ if err != nil {
136+ return E .Cause (err , "parse ECH keys" )
137+ }
138+ echKeySet , err := cftls .EXP_NewECHKeySet (echKeys )
139+ if err != nil {
140+ return E .Cause (err , "create ECH key set" )
141+ }
142+ c .config .ServerECHProvider = echKeySet
143+ c .logger .Info ("reloaded ECH keys" )
187144 }
188- }
189-
190- func (c * echServerConfig ) reloadECHKey () error {
191- echKeyContent , err := os .ReadFile (c .echKeyPath )
192- if err != nil {
193- return err
194- }
195- block , rest := pem .Decode (echKeyContent )
196- if block == nil || block .Type != "ECH KEYS" || len (rest ) > 0 {
197- return E .New ("invalid ECH keys pem" )
198- }
199- echKeys , err := cftls .EXP_UnmarshalECHKeys (block .Bytes )
200- if err != nil {
201- return E .Cause (err , "parse ECH keys" )
202- }
203- echKeySet , err := cftls .EXP_NewECHKeySet (echKeys )
204- if err != nil {
205- return E .Cause (err , "create ECH key set" )
206- }
207- c .config .ServerECHProvider = echKeySet
208- c .logger .Info ("reloaded ECH keys" )
209145 return nil
210146}
211147
212148func (c * echServerConfig ) Close () error {
213149 var err error
214150 if c .watcher != nil {
215151 err = E .Append (err , c .watcher .Close (), func (err error ) error {
216- return E .Cause (err , "close certificate watcher" )
217- })
218- }
219- if c .echWatcher != nil {
220- err = E .Append (err , c .echWatcher .Close (), func (err error ) error {
221- return E .Cause (err , "close ECH key watcher" )
152+ return E .Cause (err , "close credentials watcher" )
222153 })
223154 }
224155 return err
0 commit comments