Refactor package structure, reduce overengineering
This commit is contained in:
parent
dcabc3f136
commit
28370010f9
@ -1,4 +1,4 @@
|
|||||||
package mullsox
|
package mullvad
|
||||||
|
|
||||||
const useragent = "mullsox/0.0.1"
|
const useragent = "mullsox/0.0.1"
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
package mullsox
|
package mullvad
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -142,7 +142,7 @@ func (c *Checker) AmIMullvad(ctx context.Context) (MullvadServer, error) {
|
|||||||
return MullvadServer{}, err
|
return MullvadServer{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.Update()
|
err = c.update()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return MullvadServer{}, err
|
return MullvadServer{}, err
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package mullsox
|
package mullvad
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
@ -1,4 +1,4 @@
|
|||||||
package mullsox
|
package mullvad
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
@ -80,7 +80,7 @@ func getContentSize(url string) int {
|
|||||||
return res.Header.ContentLength()
|
return res.Header.ContentLength()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Checker) Update() error {
|
func (c *Checker) update() error {
|
||||||
var serverSlice []MullvadServer
|
var serverSlice []MullvadServer
|
||||||
if c.cachedSize > 0 {
|
if c.cachedSize > 0 {
|
||||||
latestSize := getContentSize(c.url)
|
latestSize := getContentSize(c.url)
|
||||||
@ -114,3 +114,10 @@ func (c *Checker) Update() error {
|
|||||||
c.Unlock()
|
c.Unlock()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Checker) GetRelays() ([]MullvadServer, error) {
|
||||||
|
if err := c.update(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return c.Slice(), nil
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package mullsox
|
package mullvad
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
@ -8,7 +8,7 @@ func TestGetMullvadServers(t *testing.T) {
|
|||||||
servers := NewChecker()
|
servers := NewChecker()
|
||||||
|
|
||||||
update := func() {
|
update := func() {
|
||||||
err := servers.Update()
|
err := servers.update()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("%s", err.Error())
|
t.Fatalf("%s", err.Error())
|
||||||
}
|
}
|
138
sox.go
138
sox.go
@ -6,49 +6,55 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"git.tcp.direct/kayos/mullsox/mullvad"
|
||||||
)
|
)
|
||||||
|
|
||||||
func persistentResolver(hostname string) []netip.Addr {
|
const MullvadInternalDNS4 = "10.64.0.1:53"
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
const MullvadInternalDNS6 = "[fc00:bbbb:bbbb:bb01::2b:e7d3]:53"
|
||||||
defer cancel()
|
|
||||||
var ips []netip.Addr
|
type RelayFetcher interface {
|
||||||
if hostname == "" {
|
GetRelays() ([]mullvad.MullvadServer, error)
|
||||||
return ips
|
|
||||||
}
|
|
||||||
for n := 0; n < 5; n++ {
|
|
||||||
var err error
|
|
||||||
var res []netip.Addr
|
|
||||||
go func() {
|
|
||||||
res, err = net.DefaultResolver.LookupNetIP(ctx, "ip", hostname)
|
|
||||||
if err == nil && res != nil && len(res) > 0 {
|
|
||||||
ips = res
|
|
||||||
cancel()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
}
|
|
||||||
<-ctx.Done()
|
|
||||||
return ips
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Checker) GetSOCKS() (sox []netip.AddrPort, err error) {
|
func GetSOCKS(fetcher RelayFetcher) (sox []netip.AddrPort, err error) {
|
||||||
if err = c.Update(); err != nil {
|
relays, err := fetcher.GetRelays()
|
||||||
return
|
switch {
|
||||||
|
case err != nil:
|
||||||
|
return nil, err
|
||||||
|
case len(relays) == 0:
|
||||||
|
return nil, fmt.Errorf("no relays found")
|
||||||
|
default:
|
||||||
}
|
}
|
||||||
var tmpMap = make(map[netip.AddrPort]struct{})
|
var tmpMap = make(map[netip.AddrPort]struct{})
|
||||||
var tmpMapMu = &sync.RWMutex{}
|
var tmpMapMu = &sync.RWMutex{}
|
||||||
wg := &sync.WaitGroup{}
|
wg := &sync.WaitGroup{}
|
||||||
for _, serv := range c.m {
|
for _, serv := range relays {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(endpoint *MullvadServer) {
|
go func(endpoint *mullvad.MullvadServer) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
ips := persistentResolver(endpoint.SocksName)
|
var ips []net.IP
|
||||||
for _, ip := range ips {
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
ips, err = net.DefaultResolver.LookupIP(ctx, "ip", endpoint.SocksName)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(ips) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, ipa := range ips {
|
||||||
|
var ip netip.Addr
|
||||||
port := uint16(endpoint.SocksPort)
|
port := uint16(endpoint.SocksPort)
|
||||||
if port == 0 {
|
if port == 0 {
|
||||||
port = 1080
|
port = 1080
|
||||||
}
|
}
|
||||||
|
ip, err = netip.ParseAddr(ipa.String())
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
ap := netip.AddrPortFrom(ip, port)
|
ap := netip.AddrPortFrom(ip, port)
|
||||||
tmpMapMu.RLock()
|
tmpMapMu.RLock()
|
||||||
_, ok := tmpMap[ap]
|
_, ok := tmpMap[ap]
|
||||||
@ -71,36 +77,60 @@ func (c *Checker) GetSOCKS() (sox []netip.AddrPort, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Checker) GetAndVerifySOCKS() (chan netip.AddrPort, chan error) {
|
func checker(candidate netip.AddrPort, verified chan netip.AddrPort, errs chan error, working *int64) {
|
||||||
sox, err := c.GetSOCKS()
|
atomic.AddInt64(working, 1)
|
||||||
var errs = make(chan error, len(sox)+1)
|
defer func() {
|
||||||
var verified = make(chan netip.AddrPort, len(sox))
|
time.Sleep(10 * time.Millisecond)
|
||||||
if err != nil || len(sox) == 0 {
|
atomic.AddInt64(working, -1)
|
||||||
errs <- err
|
}()
|
||||||
close(errs)
|
if !candidate.IsValid() {
|
||||||
return nil, errs
|
errs <- fmt.Errorf("invalid address/port combo: %s", candidate.String())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
wg := &sync.WaitGroup{}
|
var conn net.Conn
|
||||||
wg.Add(len(sox))
|
conn, err := net.DialTimeout("tcp", candidate.String(), 15*time.Second)
|
||||||
|
if err != nil {
|
||||||
|
errs <- err
|
||||||
|
}
|
||||||
|
if conn != nil {
|
||||||
|
_ = conn.Close()
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
verified <- candidate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAndVerifySOCKS(fetcher RelayFetcher) (chan netip.AddrPort, chan error) {
|
||||||
|
sox, err := GetSOCKS(fetcher)
|
||||||
|
var errs = make(chan error, len(sox)+1)
|
||||||
|
switch {
|
||||||
|
case len(sox) == 0:
|
||||||
|
err = fmt.Errorf("no relays found")
|
||||||
|
fallthrough
|
||||||
|
case err != nil:
|
||||||
|
go func() {
|
||||||
|
errs <- err
|
||||||
|
}()
|
||||||
|
return nil, errs
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
verified = make(chan netip.AddrPort, len(sox))
|
||||||
|
working = new(int64)
|
||||||
|
)
|
||||||
|
atomic.StoreInt64(working, 0)
|
||||||
|
|
||||||
for _, prx := range sox {
|
for _, prx := range sox {
|
||||||
time.Sleep(250 * time.Millisecond)
|
for atomic.LoadInt64(working) > 10 {
|
||||||
go func(prx netip.AddrPort) {
|
time.Sleep(50 * time.Millisecond)
|
||||||
defer wg.Done()
|
}
|
||||||
var conn net.Conn
|
checker(prx, verified, errs, working)
|
||||||
conn, err = net.DialTimeout("tcp", prx.String(), 10*time.Second)
|
|
||||||
if err != nil {
|
|
||||||
errs <- err
|
|
||||||
}
|
|
||||||
if conn != nil {
|
|
||||||
_ = conn.Close()
|
|
||||||
}
|
|
||||||
if err == nil {
|
|
||||||
verified <- prx
|
|
||||||
}
|
|
||||||
}(prx)
|
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
wg.Wait()
|
for atomic.LoadInt64(working) > 0 {
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
}
|
||||||
close(errs)
|
close(errs)
|
||||||
close(verified)
|
close(verified)
|
||||||
}()
|
}()
|
||||||
|
14
sox_test.go
14
sox_test.go
@ -2,15 +2,14 @@ package mullsox
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"git.tcp.direct/kayos/mullsox/mullvad"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestChecker_GetSOCKS(t *testing.T) {
|
func TestChecker_GetSOCKS(t *testing.T) {
|
||||||
c := NewChecker()
|
c := mullvad.NewChecker()
|
||||||
t.Run("GetSOCKS", func(t *testing.T) {
|
t.Run("GetSOCKS", func(t *testing.T) {
|
||||||
if err := c.Update(); err != nil {
|
gotSox, err := GetSOCKS(c)
|
||||||
t.Fatalf("%s", err.Error())
|
|
||||||
}
|
|
||||||
gotSox, err := c.GetSOCKS()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -22,10 +21,7 @@ func TestChecker_GetSOCKS(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("GetAndVerifySOCKS", func(t *testing.T) {
|
t.Run("GetAndVerifySOCKS", func(t *testing.T) {
|
||||||
if err := c.Update(); err != nil {
|
gotSox, errs := GetAndVerifySOCKS(c)
|
||||||
t.Fatalf("%s", err.Error())
|
|
||||||
}
|
|
||||||
gotSox, errs := c.GetAndVerifySOCKS()
|
|
||||||
count := 0
|
count := 0
|
||||||
for sox := range gotSox {
|
for sox := range gotSox {
|
||||||
select {
|
select {
|
||||||
|
Loading…
Reference in New Issue
Block a user