4
4
"context"
5
5
"crypto/tls"
6
6
"io"
7
- "math/rand"
8
7
"net"
9
8
"net/http"
10
9
"net/url"
@@ -18,7 +17,6 @@ import (
18
17
qtls "github.com/metacubex/sing-quic"
19
18
hyCC "github.com/metacubex/sing-quic/hysteria2/congestion"
20
19
"github.com/metacubex/sing-quic/hysteria2/internal/protocol"
21
- "github.com/sagernet/sing/common/atomic"
22
20
"github.com/sagernet/sing/common/baderror"
23
21
E "github.com/sagernet/sing/common/exceptions"
24
22
"github.com/sagernet/sing/common/logger"
@@ -31,8 +29,7 @@ type ClientOptions struct {
31
29
Dialer N.Dialer
32
30
Logger logger.Logger
33
31
BrutalDebug bool
34
- ServerAddress M.Socksaddr
35
- ServerAddresses []M.Socksaddr
32
+ ServerAddress func (ctx context.Context ) (* net.UDPAddr , error )
36
33
HopInterval time.Duration
37
34
SendBPS uint64
38
35
ReceiveBPS uint64
@@ -49,8 +46,7 @@ type Client struct {
49
46
dialer N.Dialer
50
47
logger logger.Logger
51
48
brutalDebug bool
52
- serverAddr atomic.TypedValue [M.Socksaddr ]
53
- serverAddrs []M.Socksaddr
49
+ serverAddress func (ctx context.Context ) (* net.UDPAddr , error )
54
50
hopInterval time.Duration
55
51
sendBPS uint64
56
52
receiveBPS uint64
@@ -85,7 +81,7 @@ func NewClient(options ClientOptions) (*Client, error) {
85
81
dialer : options .Dialer ,
86
82
logger : options .Logger ,
87
83
brutalDebug : options .BrutalDebug ,
88
- serverAddrs : options .ServerAddresses ,
84
+ serverAddress : options .ServerAddress ,
89
85
hopInterval : options .HopInterval ,
90
86
sendBPS : options .SendBPS ,
91
87
receiveBPS : options .ReceiveBPS ,
@@ -97,27 +93,31 @@ func NewClient(options ClientOptions) (*Client, error) {
97
93
cwnd : options .CWND ,
98
94
udpMTU : options .UdpMTU ,
99
95
}
100
- client .serverAddr .Store (options .ServerAddress )
101
96
return client , nil
102
97
}
103
98
104
99
func (c * Client ) hopLoop (conn * clientQUICConnection ) {
105
100
ticker := time .NewTicker (c .hopInterval )
106
101
defer ticker .Stop ()
107
- c .logger .Info ("Entering hop loop ..." )
102
+ c .logger .Debug ("Entering hop loop ..." )
108
103
for {
109
104
select {
110
105
case <- ticker .C :
111
- serverAddr := c .serverAddrs [rand .Intn (len (c .serverAddrs ))]
112
- c .serverAddr .Store (serverAddr )
113
- conn .quicConn .SetRemoteAddr (serverAddr .UDPAddr ())
114
- c .logger .Info ("Hopped to " , serverAddr )
106
+ ctx , cancel := context .WithTimeout (context .Background (), c .hopInterval )
107
+ serverAddr , err := c .serverAddress (ctx )
108
+ cancel ()
109
+ if err != nil {
110
+ c .logger .Warn ("Hop loop fetch serverAddress error: '%s', ignored" , err )
111
+ break
112
+ }
113
+ conn .quicConn .SetRemoteAddr (serverAddr )
114
+ c .logger .Debug ("Hopped to " , serverAddr )
115
115
continue
116
116
case <- c .ctx .Done ():
117
117
case <- conn .quicConn .Context ().Done ():
118
118
case <- conn .connDone :
119
119
}
120
- c .logger .Info ("Exiting hop loop ..." )
120
+ c .logger .Debug ("Exiting hop loop ..." )
121
121
return
122
122
}
123
123
}
@@ -141,8 +141,11 @@ func (c *Client) offer(ctx context.Context) (*clientQUICConnection, error) {
141
141
}
142
142
143
143
func (c * Client ) offerNew (ctx context.Context ) (* clientQUICConnection , error ) {
144
- serverAddr := c .serverAddr .Load ()
145
- packetConn , err := c .dialer .ListenPacket (ctx , serverAddr )
144
+ serverAddr , err := c .serverAddress (ctx )
145
+ if err == nil {
146
+ return nil , err
147
+ }
148
+ packetConn , err := c .dialer .ListenPacket (ctx , M .SocksaddrFromNet (serverAddr ))
146
149
if err != nil {
147
150
return nil , err
148
151
}
@@ -202,7 +205,7 @@ func (c *Client) offerNew(ctx context.Context) (*clientQUICConnection, error) {
202
205
go c .loopMessages (conn )
203
206
}
204
207
c .conn = conn
205
- if len ( c . serverAddrs ) > 0 {
208
+ if c . hopInterval > 0 {
206
209
go c .hopLoop (conn )
207
210
}
208
211
return conn , nil
0 commit comments