clash/adapters/outbound/urltest.go

103 lines
1.6 KiB
Go
Raw Normal View History

2018-06-16 13:34:13 +00:00
package adapters
import (
"sync"
"time"
C "github.com/Dreamacro/clash/constant"
)
type URLTest struct {
2018-07-18 13:50:16 +00:00
name string
proxies []C.Proxy
rawURL string
fast C.Proxy
delay time.Duration
done chan struct{}
2018-06-16 13:34:13 +00:00
}
func (u *URLTest) Name() string {
return u.name
}
func (u *URLTest) Type() C.AdapterType {
return C.URLTest
}
func (u *URLTest) Now() string {
return u.fast.Name()
}
2018-09-30 04:25:52 +00:00
func (u *URLTest) Generator(metadata *C.Metadata) (adapter C.ProxyAdapter, err error) {
return u.fast.Generator(metadata)
2018-06-16 13:34:13 +00:00
}
func (u *URLTest) Close() {
u.done <- struct{}{}
}
2018-06-16 13:34:13 +00:00
func (u *URLTest) loop() {
tick := time.NewTicker(u.delay)
2018-06-16 13:34:13 +00:00
go u.speedTest()
Loop:
for {
select {
case <-tick.C:
go u.speedTest()
case <-u.done:
break Loop
}
2018-06-16 13:34:13 +00:00
}
}
func (u *URLTest) speedTest() {
wg := sync.WaitGroup{}
2018-07-18 13:50:16 +00:00
wg.Add(len(u.proxies))
2018-06-16 13:34:13 +00:00
c := make(chan interface{})
fast := selectFast(c)
timer := time.NewTimer(u.delay)
2018-07-18 13:50:16 +00:00
for _, p := range u.proxies {
2018-06-16 13:34:13 +00:00
go func(p C.Proxy) {
2018-08-08 03:51:06 +00:00
_, err := DelayTest(p, u.rawURL)
2018-06-16 13:34:13 +00:00
if err == nil {
c <- p
}
wg.Done()
}(p)
}
go func() {
wg.Wait()
close(c)
}()
select {
case <-timer.C:
// Wait for fast to return or close.
<-fast
case p, open := <-fast:
if open {
u.fast = p.(C.Proxy)
}
}
}
2018-07-18 13:50:16 +00:00
func NewURLTest(name string, proxies []C.Proxy, rawURL string, delay time.Duration) (*URLTest, error) {
2018-09-30 04:25:52 +00:00
_, err := urlToMetadata(rawURL)
2018-06-16 13:34:13 +00:00
if err != nil {
return nil, err
}
urlTest := &URLTest{
2018-07-18 13:50:16 +00:00
name: name,
proxies: proxies[:],
rawURL: rawURL,
fast: proxies[0],
delay: delay,
done: make(chan struct{}),
2018-06-16 13:34:13 +00:00
}
go urlTest.loop()
return urlTest, nil
}