prox5/mystery_dialer.go

77 lines
2.0 KiB
Go
Raw Normal View History

2022-05-23 01:05:50 +00:00
package prox5
import (
2021-09-14 01:50:39 +00:00
"context"
2021-09-28 06:25:00 +00:00
"errors"
"fmt"
"net"
2021-09-29 08:31:19 +00:00
"strconv"
"sync/atomic"
"time"
"h12.io/socks"
)
// DialContext is a simple stub adapter to implement a net.Dialer with context.
2021-09-28 06:25:00 +00:00
func (s *Swamp) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
return s.MysteryDialer(ctx, network, addr)
}
// Dial is a simple stub adapter to implement a net.Dialer.
2022-07-09 18:36:45 +00:00
func (s *Swamp) Dial(network, addr string) (net.Conn, error) {
return s.DialContext(context.Background(), network, addr)
}
// DialTimeout is a simple stub adapter to implement a net.Dialer with a timeout.
func (s *Swamp) DialTimeout(network, addr string, timeout time.Duration) (net.Conn, error) {
2022-07-15 08:36:54 +00:00
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(timeout))
2022-07-25 06:24:06 +00:00
go func() {
select {
case <-ctx.Done():
cancel()
}
}()
return s.MysteryDialer(ctx, network, addr)
}
// MysteryDialer is a dialer function that will use a different proxy for every request.
func (s *Swamp) MysteryDialer(ctx context.Context, network, addr string) (net.Conn, error) {
var sock *Proxy
var conn net.Conn
2021-09-28 06:25:00 +00:00
var count int
// pull down proxies from channel until we get a proxy good enough for our spoiled asses
for {
2021-09-29 08:31:19 +00:00
max := s.GetDialerBailout()
if count > max {
return nil, errors.New("giving up after " + strconv.Itoa(max) + " tries")
2021-09-28 06:25:00 +00:00
}
if err := ctx.Err(); err != nil {
return nil, fmt.Errorf("context error: %v", err)
}
sock = s.GetAnySOCKS()
for !atomic.CompareAndSwapUint32(&sock.lock, stateUnlocked, stateLocked) {
if sock == nil {
break
}
randSleep()
}
if sock == nil {
continue
}
s.dbgPrint("dialer trying: " + sock.Endpoint + "...")
atomic.StoreUint32(&sock.lock, stateUnlocked)
dialSocks := socks.Dial(sock.String())
var err error
if conn, err = dialSocks(network, addr); err != nil {
2021-09-28 06:25:00 +00:00
count++
s.dbgPrint(ylw + "unable to reach [redacted] with " + sock.String() + ", cycling..." + rst)
2021-09-24 16:38:57 +00:00
continue
}
break
}
s.dbgPrint(grn + "MysteryDialer using socks: " + sock.String() + rst)
return conn, nil
}