@@ -23,6 +23,15 @@ const (
2323 Shadowsocks = "shadowsocks"
2424)
2525
26+ // extractIDFromEmail extracts the ID part from an email in the format "id.username"
27+ // If no dot is found, returns the full email string
28+ func extractIDFromEmail (email string ) string {
29+ if idx := strings .Index (email , "." ); idx != - 1 {
30+ return email [:idx ]
31+ }
32+ return email
33+ }
34+
2635type Config struct {
2736 LogConfig * conf.LogConfig `json:"log"`
2837 RouterConfig * conf.RouterConfig `json:"routing"`
@@ -68,19 +77,23 @@ func (i *Inbound) syncUsers(users []*common.User) {
6877 switch i .Protocol {
6978 case Vmess :
7079 clients := make ([]* api.VmessAccount , 0 , len (users ))
71-
7280 for _ , user := range users {
7381 if user .GetProxies ().GetVmess () == nil {
7482 continue
7583 }
76- account , err := api .NewVmessAccount (user )
77- if err != nil {
78- log .Println ("error for user" , user .GetEmail (), ":" , err )
79- }
8084 if slices .Contains (user .Inbounds , i .Tag ) {
85+ account , err := api .NewVmessAccount (user )
86+ if err != nil {
87+ log .Println ("error for user" , user .GetEmail (), ":" , err )
88+ continue
89+ }
8190 clients = append (clients , account )
8291 }
8392 }
93+ // Keep sorted by ID (part before dot in email) for binary search
94+ slices .SortFunc (clients , func (a , b * api.VmessAccount ) int {
95+ return strings .Compare (extractIDFromEmail (a .Email ), extractIDFromEmail (b .Email ))
96+ })
8497 i .Settings ["clients" ] = clients
8598
8699 case Vless :
@@ -89,15 +102,20 @@ func (i *Inbound) syncUsers(users []*common.User) {
89102 if user .GetProxies ().GetVless () == nil {
90103 continue
91104 }
92- account , err := api .NewVlessAccount (user )
93- if err != nil {
94- log .Println ("error for user" , user .GetEmail (), ":" , err )
95- }
96105 if slices .Contains (user .Inbounds , i .Tag ) {
106+ account , err := api .NewVlessAccount (user )
107+ if err != nil {
108+ log .Println ("error for user" , user .GetEmail (), ":" , err )
109+ continue
110+ }
97111 newAccount := checkVless (i , * account )
98112 clients = append (clients , & newAccount )
99113 }
100114 }
115+ // Keep sorted by ID (part before dot in email) for binary search
116+ slices .SortFunc (clients , func (a , b * api.VlessAccount ) int {
117+ return strings .Compare (extractIDFromEmail (a .Email ), extractIDFromEmail (b .Email ))
118+ })
101119 i .Settings ["clients" ] = clients
102120
103121 case Trojan :
@@ -110,6 +128,10 @@ func (i *Inbound) syncUsers(users []*common.User) {
110128 clients = append (clients , api .NewTrojanAccount (user ))
111129 }
112130 }
131+ // Keep sorted by ID (part before dot in email) for binary search
132+ slices .SortFunc (clients , func (a , b * api.TrojanAccount ) int {
133+ return strings .Compare (extractIDFromEmail (a .Email ), extractIDFromEmail (b .Email ))
134+ })
113135 i .Settings ["clients" ] = clients
114136
115137 case Shadowsocks :
@@ -126,8 +148,11 @@ func (i *Inbound) syncUsers(users []*common.User) {
126148 clients = append (clients , & newAccount )
127149 }
128150 }
151+ // Keep sorted by ID (part before dot in email) for binary search
152+ slices .SortFunc (clients , func (a , b * api.ShadowsocksAccount ) int {
153+ return strings .Compare (extractIDFromEmail (a .Email ), extractIDFromEmail (b .Email ))
154+ })
129155 i .Settings ["clients" ] = clients
130-
131156 } else {
132157 clients := make ([]* api.ShadowsocksTcpAccount , 0 , len (users ))
133158 for _ , user := range users {
@@ -138,6 +163,10 @@ func (i *Inbound) syncUsers(users []*common.User) {
138163 clients = append (clients , api .NewShadowsocksTcpAccount (user ))
139164 }
140165 }
166+ // Keep sorted by ID (part before dot in email) for binary search
167+ slices .SortFunc (clients , func (a , b * api.ShadowsocksTcpAccount ) int {
168+ return strings .Compare (extractIDFromEmail (a .Email ), extractIDFromEmail (b .Email ))
169+ })
141170 i .Settings ["clients" ] = clients
142171 }
143172 }
@@ -148,180 +177,163 @@ func (i *Inbound) updateUser(account api.Account) {
148177 defer i .mu .Unlock ()
149178
150179 email := account .GetEmail ()
151- switch account .(type ) {
180+ searchID := extractIDFromEmail (email )
181+ switch a := account .(type ) {
152182 case * api.VmessAccount :
153- clients , ok := i .Settings ["clients" ].([]* api.VmessAccount )
154- if ! ok {
155- clients = []* api.VmessAccount {}
156- }
157-
158- for x , client := range clients {
159- if client .Email == email {
160- clients = append (clients [:x ], clients [x + 1 :]... )
161- break
162- }
183+ clients , _ := i .Settings ["clients" ].([]* api.VmessAccount )
184+ if idx , found := slices .BinarySearchFunc (clients , searchID , func (c * api.VmessAccount , id string ) int {
185+ return strings .Compare (extractIDFromEmail (c .Email ), id )
186+ }); found {
187+ clients = append (clients [:idx ], clients [idx + 1 :]... )
163188 }
164-
165- i .Settings ["clients" ] = append (clients , account .(* api.VmessAccount ))
189+ insertIdx , _ := slices .BinarySearchFunc (clients , searchID , func (c * api.VmessAccount , id string ) int {
190+ return strings .Compare (extractIDFromEmail (c .Email ), id )
191+ })
192+ clients = append (clients , nil )
193+ copy (clients [insertIdx + 1 :], clients [insertIdx :])
194+ clients [insertIdx ] = a
195+ i .Settings ["clients" ] = clients
166196
167197 case * api.VlessAccount :
168- clients , ok := i .Settings ["clients" ].([]* api.VlessAccount )
169- if ! ok {
170- clients = []* api.VlessAccount {}
171- }
172-
173- for x , client := range clients {
174- if client .Email == email {
175- clients = append (clients [:x ], clients [x + 1 :]... )
176- break
177- }
198+ clients , _ := i .Settings ["clients" ].([]* api.VlessAccount )
199+ if idx , found := slices .BinarySearchFunc (clients , searchID , func (c * api.VlessAccount , id string ) int {
200+ return strings .Compare (extractIDFromEmail (c .Email ), id )
201+ }); found {
202+ clients = append (clients [:idx ], clients [idx + 1 :]... )
178203 }
179-
180- i .Settings ["clients" ] = append (clients , account .(* api.VlessAccount ))
204+ insertIdx , _ := slices .BinarySearchFunc (clients , searchID , func (c * api.VlessAccount , id string ) int {
205+ return strings .Compare (extractIDFromEmail (c .Email ), id )
206+ })
207+ clients = append (clients , nil )
208+ copy (clients [insertIdx + 1 :], clients [insertIdx :])
209+ clients [insertIdx ] = a
210+ i .Settings ["clients" ] = clients
181211
182212 case * api.TrojanAccount :
183- clients , ok := i .Settings ["clients" ].([]* api.TrojanAccount )
184- if ! ok {
185- clients = []* api.TrojanAccount {}
186- }
187-
188- for x , client := range clients {
189- if client .Email == email {
190- clients = append (clients [:x ], clients [x + 1 :]... )
191- break
192- }
213+ clients , _ := i .Settings ["clients" ].([]* api.TrojanAccount )
214+ if idx , found := slices .BinarySearchFunc (clients , searchID , func (c * api.TrojanAccount , id string ) int {
215+ return strings .Compare (extractIDFromEmail (c .Email ), id )
216+ }); found {
217+ clients = append (clients [:idx ], clients [idx + 1 :]... )
193218 }
194-
195- i .Settings ["clients" ] = append (clients , account .(* api.TrojanAccount ))
219+ insertIdx , _ := slices .BinarySearchFunc (clients , searchID , func (c * api.TrojanAccount , id string ) int {
220+ return strings .Compare (extractIDFromEmail (c .Email ), id )
221+ })
222+ clients = append (clients , nil )
223+ copy (clients [insertIdx + 1 :], clients [insertIdx :])
224+ clients [insertIdx ] = a
225+ i .Settings ["clients" ] = clients
196226
197227 case * api.ShadowsocksTcpAccount :
198- clients , ok := i .Settings ["clients" ].([]* api.ShadowsocksTcpAccount )
199- if ! ok {
200- clients = []* api.ShadowsocksTcpAccount {}
201- }
202-
203- for x , client := range clients {
204- if client .Email == email {
205- clients = append (clients [:x ], clients [x + 1 :]... )
206- break
207- }
228+ clients , _ := i .Settings ["clients" ].([]* api.ShadowsocksTcpAccount )
229+ if idx , found := slices .BinarySearchFunc (clients , searchID , func (c * api.ShadowsocksTcpAccount , id string ) int {
230+ return strings .Compare (extractIDFromEmail (c .Email ), id )
231+ }); found {
232+ clients = append (clients [:idx ], clients [idx + 1 :]... )
208233 }
209-
210- i .Settings ["clients" ] = append (clients , account .(* api.ShadowsocksTcpAccount ))
234+ insertIdx , _ := slices .BinarySearchFunc (clients , searchID , func (c * api.ShadowsocksTcpAccount , id string ) int {
235+ return strings .Compare (extractIDFromEmail (c .Email ), id )
236+ })
237+ clients = append (clients , nil )
238+ copy (clients [insertIdx + 1 :], clients [insertIdx :])
239+ clients [insertIdx ] = a
240+ i .Settings ["clients" ] = clients
211241
212242 case * api.ShadowsocksAccount :
213- clients , ok := i .Settings ["clients" ].([]* api.ShadowsocksAccount )
214- if ! ok {
215- clients = []* api.ShadowsocksAccount {}
243+ clients , _ := i .Settings ["clients" ].([]* api.ShadowsocksAccount )
244+ if idx , found := slices .BinarySearchFunc (clients , searchID , func (c * api.ShadowsocksAccount , id string ) int {
245+ return strings .Compare (extractIDFromEmail (c .Email ), id )
246+ }); found {
247+ clients = append (clients [:idx ], clients [idx + 1 :]... )
216248 }
217-
218- for x , client := range clients {
219- if client .Email == email {
220- clients = append (clients [:x ], clients [x + 1 :]... )
221- break
222- }
249+ method , ok := i .Settings ["method" ].(string )
250+ var newAccount * api.ShadowsocksAccount
251+ if ok {
252+ na := checkShadowsocks2022 (method , * a )
253+ newAccount = & na
254+ } else {
255+ newAccount = a
223256 }
224-
225- method := i . Settings [ "method" ].( string )
226- newAccount := checkShadowsocks2022 ( method , * account .( * api. ShadowsocksAccount ) )
227- i . Settings [ " clients" ] = append (clients , & newAccount )
228-
229- default :
230- return
257+ insertIdx , _ := slices . BinarySearchFunc ( clients , searchID , func ( c * api. ShadowsocksAccount , id string ) int {
258+ return strings . Compare ( extractIDFromEmail ( c . Email ), id )
259+ } )
260+ clients = append (clients , nil )
261+ copy ( clients [ insertIdx + 1 :], clients [ insertIdx :])
262+ clients [ insertIdx ] = newAccount
263+ i . Settings [ "clients" ] = clients
231264 }
232265}
233266
234267func (i * Inbound ) removeUser (email string ) {
235268 i .mu .Lock ()
236269 defer i .mu .Unlock ()
237270
271+ searchID := extractIDFromEmail (email )
238272 switch Protocol (i .Protocol ) {
239273 case Vmess :
240- clients , ok := i .Settings ["clients" ].([]* api.VmessAccount )
241- if ! ok {
242- clients = []* api.VmessAccount {}
243- }
244-
245- for x , client := range clients {
246- if client .Email == email {
247- clients = append (clients [:x ], clients [x + 1 :]... )
248- break
249- }
274+ clients , _ := i .Settings ["clients" ].([]* api.VmessAccount )
275+ if idx , found := slices .BinarySearchFunc (clients , searchID , func (c * api.VmessAccount , id string ) int {
276+ return strings .Compare (extractIDFromEmail (c .Email ), id )
277+ }); found {
278+ clients = append (clients [:idx ], clients [idx + 1 :]... )
250279 }
251280 i .Settings ["clients" ] = clients
252281
253282 case Vless :
254- clients , ok := i .Settings ["clients" ].([]* api.VlessAccount )
255- if ! ok {
256- clients = []* api.VlessAccount {}
257- }
258-
259- for x , client := range clients {
260- if client .Email == email {
261- clients = append (clients [:x ], clients [x + 1 :]... )
262- break
263- }
283+ clients , _ := i .Settings ["clients" ].([]* api.VlessAccount )
284+ if idx , found := slices .BinarySearchFunc (clients , searchID , func (c * api.VlessAccount , id string ) int {
285+ return strings .Compare (extractIDFromEmail (c .Email ), id )
286+ }); found {
287+ clients = append (clients [:idx ], clients [idx + 1 :]... )
264288 }
265289 i .Settings ["clients" ] = clients
266290
267291 case Trojan :
268- clients , ok := i .Settings ["clients" ].([]* api.TrojanAccount )
269- if ! ok {
270- clients = []* api.TrojanAccount {}
271- }
272-
273- for x , client := range clients {
274- if client .Email == email {
275- clients = append (clients [:x ], clients [x + 1 :]... )
276- break
277- }
292+ clients , _ := i .Settings ["clients" ].([]* api.TrojanAccount )
293+ if idx , found := slices .BinarySearchFunc (clients , searchID , func (c * api.TrojanAccount , id string ) int {
294+ return strings .Compare (extractIDFromEmail (c .Email ), id )
295+ }); found {
296+ clients = append (clients [:idx ], clients [idx + 1 :]... )
278297 }
279298 i .Settings ["clients" ] = clients
280299
281300 case Shadowsocks :
282301 method , methodOk := i .Settings ["method" ].(string )
283302 if methodOk && strings .HasPrefix (method , "2022-blake3" ) {
284- clients , ok := i .Settings ["clients" ].([]* api.ShadowsocksAccount )
285- if ! ok {
286- clients = []* api.ShadowsocksAccount {}
287- }
288-
289- for x , client := range clients {
290- if client .Email == email {
291- clients = append (clients [:x ], clients [x + 1 :]... )
292- break
293- }
303+ clients , _ := i .Settings ["clients" ].([]* api.ShadowsocksAccount )
304+ if idx , found := slices .BinarySearchFunc (clients , searchID , func (c * api.ShadowsocksAccount , id string ) int {
305+ return strings .Compare (extractIDFromEmail (c .Email ), id )
306+ }); found {
307+ clients = append (clients [:idx ], clients [idx + 1 :]... )
294308 }
295309 i .Settings ["clients" ] = clients
296-
297310 } else {
298- clients , ok := i .Settings ["clients" ].([]* api.ShadowsocksTcpAccount )
299- if ! ok {
300- clients = []* api.ShadowsocksTcpAccount {}
301- }
302-
303- for x , client := range clients {
304- if client .Email == email {
305- clients = append (clients [:x ], clients [x + 1 :]... )
306- break
307- }
311+ clients , _ := i .Settings ["clients" ].([]* api.ShadowsocksTcpAccount )
312+ if idx , found := slices .BinarySearchFunc (clients , searchID , func (c * api.ShadowsocksTcpAccount , id string ) int {
313+ return strings .Compare (extractIDFromEmail (c .Email ), id )
314+ }); found {
315+ clients = append (clients [:idx ], clients [idx + 1 :]... )
308316 }
309317 i .Settings ["clients" ] = clients
310318 }
311- default :
312- return
313319 }
314320}
315321
316322type Stats struct {}
317323
318324func (c * Config ) ToBytes () ([]byte , error ) {
325+ // Acquire read locks for all inbounds
319326 for _ , i := range c .InboundConfigs {
320327 i .mu .RLock ()
321- defer i .mu .RUnlock ()
322328 }
323329
324330 b , err := json .Marshal (c )
331+
332+ // Release all locks
333+ for _ , i := range c .InboundConfigs {
334+ i .mu .RUnlock ()
335+ }
336+
325337 if err != nil {
326338 return nil , err
327339 }
0 commit comments