|
|
@@ -4,8 +4,11 @@ import (
|
|
|
"context"
|
|
|
"encoding/json"
|
|
|
"fmt"
|
|
|
+ "sync"
|
|
|
"time"
|
|
|
|
|
|
+ "github.com/ivpusic/grpool"
|
|
|
+
|
|
|
"github.com/Dreamacro/clash/adapters/outbound"
|
|
|
)
|
|
|
|
|
|
@@ -35,21 +38,75 @@ func testDelay(p Proxy) (delay uint16, err error) {
|
|
|
return delay, err
|
|
|
}
|
|
|
|
|
|
+func CleanBadProxiesWithGrpool(proxies []Proxy) (cproxies []Proxy) {
|
|
|
+ pool := grpool.NewPool(500, 200)
|
|
|
+
|
|
|
+ c := make(chan checkResult)
|
|
|
+ defer close(c)
|
|
|
+
|
|
|
+ pool.WaitCount(len(proxies))
|
|
|
+ go func() {
|
|
|
+ for _, p := range proxies {
|
|
|
+ pp := p
|
|
|
+ pool.JobQueue <- func() {
|
|
|
+ defer pool.JobDone()
|
|
|
+ delay, err := testDelay(pp)
|
|
|
+ if err == nil {
|
|
|
+ c <- checkResult{
|
|
|
+ name: pp.Identifier(),
|
|
|
+ delay: delay,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }()
|
|
|
+ done := make(chan struct{})
|
|
|
+ defer close(done)
|
|
|
+
|
|
|
+ go func() {
|
|
|
+ pool.WaitAll()
|
|
|
+ pool.Release()
|
|
|
+ done <- struct{}{}
|
|
|
+ }()
|
|
|
+
|
|
|
+ okMap := make(map[string]struct{})
|
|
|
+ for {
|
|
|
+ select {
|
|
|
+ case r := <-c:
|
|
|
+ if r.delay > 0 {
|
|
|
+ okMap[r.name] = struct{}{}
|
|
|
+ }
|
|
|
+ case <-done:
|
|
|
+ cproxies = make(ProxyList, 0, 500)
|
|
|
+ for _, p := range proxies {
|
|
|
+ if _, ok := okMap[p.Identifier()]; ok {
|
|
|
+ cproxies = append(cproxies, p.Clone())
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
func CleanBadProxies(proxies []Proxy) (cproxies []Proxy) {
|
|
|
c := make(chan checkResult, 40)
|
|
|
- defer close(c)
|
|
|
+ wg := &sync.WaitGroup{}
|
|
|
+ wg.Add(len(proxies))
|
|
|
for _, p := range proxies {
|
|
|
- go testProxyDelayToChan(p, c)
|
|
|
+ go testProxyDelayToChan(p, c, wg)
|
|
|
}
|
|
|
+ go func() {
|
|
|
+ wg.Wait()
|
|
|
+ close(c)
|
|
|
+ }()
|
|
|
+
|
|
|
okMap := make(map[string]struct{})
|
|
|
- size := len(proxies)
|
|
|
- for i := 0; i < size; i++ {
|
|
|
- r := <-c
|
|
|
+ for r := range c {
|
|
|
if r.delay > 0 {
|
|
|
okMap[r.name] = struct{}{}
|
|
|
}
|
|
|
}
|
|
|
- cproxies = make([]Proxy, 0)
|
|
|
+ cproxies = make(ProxyList, 0, 500)
|
|
|
for _, p := range proxies {
|
|
|
if _, ok := okMap[p.Identifier()]; ok {
|
|
|
cproxies = append(cproxies, p.Clone())
|
|
|
@@ -63,17 +120,13 @@ type checkResult struct {
|
|
|
delay uint16
|
|
|
}
|
|
|
|
|
|
-func testProxyDelayToChan(p Proxy, c chan checkResult) {
|
|
|
+func testProxyDelayToChan(p Proxy, c chan checkResult, wg *sync.WaitGroup) {
|
|
|
+ defer wg.Done()
|
|
|
delay, err := testDelay(p)
|
|
|
- if err != nil {
|
|
|
+ if err == nil {
|
|
|
c <- checkResult{
|
|
|
name: p.Identifier(),
|
|
|
- delay: 0,
|
|
|
+ delay: delay,
|
|
|
}
|
|
|
- return
|
|
|
- }
|
|
|
- c <- checkResult{
|
|
|
- name: p.Identifier(),
|
|
|
- delay: delay,
|
|
|
}
|
|
|
}
|