82 lines
2.1 KiB
Go
82 lines
2.1 KiB
Go
package prox5
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"net"
|
|
"strconv"
|
|
"sync/atomic"
|
|
"time"
|
|
|
|
"h12.io/socks"
|
|
)
|
|
|
|
// DialContext is a simple stub adapter to implement a net.Dialer with context.
|
|
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.
|
|
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) {
|
|
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(timeout))
|
|
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
|
|
var count int
|
|
// pull down proxies from channel until we get a proxy good enough for our spoiled asses
|
|
for {
|
|
select {
|
|
case <-ctx.Done():
|
|
return nil, ctx.Err()
|
|
default:
|
|
}
|
|
max := s.GetDialerBailout()
|
|
if count > max {
|
|
return nil, errors.New("giving up after " + strconv.Itoa(max) + " tries")
|
|
}
|
|
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 {
|
|
count++
|
|
s.dbgPrint(ylw + "unable to reach [redacted] with " + sock.String() + ", cycling..." + rst)
|
|
continue
|
|
}
|
|
break
|
|
}
|
|
s.dbgPrint(grn + "MysteryDialer using socks: " + sock.String() + rst)
|
|
return conn, nil
|
|
}
|