Consistency related adjustments

This commit is contained in:
kayos@tcp.direct 2022-09-22 16:48:08 -07:00
parent 94a2c381da
commit 209deae96f
Signed by: kayos
GPG Key ID: 4B841471B4BEE979
11 changed files with 218 additions and 220 deletions

View File

@ -19,11 +19,11 @@ const (
)
// Start starts our proxy pool operations. Trying to start a running Swamp will return an error.
func (pe *Swamp) Start() error {
if atomic.LoadUint32(&pe.Status) != uint32(StateNew) {
return pe.Resume()
func (p5 *Swamp) Start() error {
if atomic.LoadUint32(&p5.Status) != uint32(StateNew) {
return p5.Resume()
}
pe.startDaemons()
p5.startDaemons()
return nil
}
@ -34,39 +34,39 @@ Pause will cease the creation of any new proxy validation operations.
- Options may be changed and proxy lists may be loaded when paused.
- Pausing an already paused Swamp is a nonop.
*/
func (pe *Swamp) Pause() error {
if !pe.IsRunning() {
func (p5 *Swamp) Pause() error {
if !p5.IsRunning() {
return errors.New("not running")
}
pe.dbgPrint(simpleString("pausing proxy pool"))
p5.dbgPrint(simpleString("pausing proxy pool"))
pe.quit()
p5.quit()
atomic.StoreUint32(&pe.Status, uint32(StatePaused))
atomic.StoreUint32(&p5.Status, uint32(StatePaused))
return nil
}
func (pe *Swamp) startDaemons() {
go pe.mapBuilder()
<-pe.conductor
pe.svcUp()
go pe.jobSpawner()
func (p5 *Swamp) startDaemons() {
go p5.mapBuilder()
<-p5.conductor
p5.svcUp()
go p5.jobSpawner()
for {
if pe.IsRunning() {
atomic.StoreUint32(&pe.Status, uint32(StateRunning))
if p5.IsRunning() {
atomic.StoreUint32(&p5.Status, uint32(StateRunning))
break
}
}
}
// Resume will resume pause proxy pool operations, attempting to resume a running Swamp is returns an error.
func (pe *Swamp) Resume() error {
if pe.IsRunning() {
func (p5 *Swamp) Resume() error {
if p5.IsRunning() {
return errors.New("already running")
}
pe.ctx, pe.quit = context.WithCancel(context.Background())
pe.startDaemons()
p5.ctx, p5.quit = context.WithCancel(context.Background())
p5.startDaemons()
return nil
}

View File

@ -46,20 +46,20 @@ func (b *basicPrinter) Printf(format string, items ...any) {
}
// DebugEnabled returns the current state of our debug switch.
func (pe *Swamp) DebugEnabled() bool {
func (p5 *Swamp) DebugEnabled() bool {
debugHardLock.RLock()
defer debugHardLock.RUnlock()
return atomic.CompareAndSwapUint32(debugStatus, debugEnabled, debugEnabled)
}
// EnableDebug enables printing of verbose messages during operation
func (pe *Swamp) EnableDebug() {
func (p5 *Swamp) EnableDebug() {
atomic.StoreUint32(debugStatus, debugEnabled)
}
// DisableDebug enables printing of verbose messages during operation.
// WARNING: if you are using a DebugChannel, you must read all of the messages in the channel's cache or this will block.
func (pe *Swamp) DisableDebug() {
func (p5 *Swamp) DisableDebug() {
atomic.StoreUint32(debugStatus, debugDisabled)
}
@ -69,69 +69,69 @@ func simpleString(s string) *strings.Builder {
return buf
}
func (pe *Swamp) dbgPrint(builder *strings.Builder) {
func (p5 *Swamp) dbgPrint(builder *strings.Builder) {
defer pools.DiscardBuffer(builder)
if !pe.DebugEnabled() {
if !p5.DebugEnabled() {
return
}
pe.DebugLogger.Print(builder.String())
p5.DebugLogger.Print(builder.String())
return
}
func (pe *Swamp) msgUnableToReach(socksString, target string, err error) {
if !pe.DebugEnabled() {
func (p5 *Swamp) msgUnableToReach(socksString, target string, err error) {
if !p5.DebugEnabled() {
return
}
buf := pools.CopABuffer.Get().(*strings.Builder)
buf.WriteString("unable to reach ")
if pe.swampopt.redact {
if p5.swampopt.redact {
buf.WriteString("[redacted]")
} else {
buf.WriteString(target)
}
buf.WriteString(" with ")
buf.WriteString(socksString)
if !pe.swampopt.redact {
if !p5.swampopt.redact {
buf.WriteString(": ")
buf.WriteString(err.Error())
}
buf.WriteString(", cycling...")
pe.dbgPrint(buf)
p5.dbgPrint(buf)
}
func (pe *Swamp) msgUsingProxy(socksString string) {
if !pe.DebugEnabled() {
func (p5 *Swamp) msgUsingProxy(socksString string) {
if !p5.DebugEnabled() {
return
}
buf := pools.CopABuffer.Get().(*strings.Builder)
buf.WriteString("MysteryDialer using socks: ")
buf.WriteString(socksString)
pe.dbgPrint(buf)
p5.dbgPrint(buf)
}
func (pe *Swamp) msgFailedMiddleware(socksString string) {
if !pe.DebugEnabled() {
func (p5 *Swamp) msgFailedMiddleware(socksString string) {
if !p5.DebugEnabled() {
return
}
buf := pools.CopABuffer.Get().(*strings.Builder)
buf.WriteString("failed middleware check, ")
buf.WriteString(socksString)
buf.WriteString(", cycling...")
pe.dbgPrint(buf)
p5.dbgPrint(buf)
}
func (pe *Swamp) msgTry(socksString string) {
if !pe.DebugEnabled() {
func (p5 *Swamp) msgTry(socksString string) {
if !p5.DebugEnabled() {
return
}
buf := pools.CopABuffer.Get().(*strings.Builder)
buf.WriteString("try dial with: ")
buf.WriteString(socksString)
pe.dbgPrint(buf)
p5.dbgPrint(buf)
}
func (pe *Swamp) msgCantGetLock(socksString string, putback bool) {
if !pe.DebugEnabled() {
func (p5 *Swamp) msgCantGetLock(socksString string, putback bool) {
if !p5.DebugEnabled() {
return
}
buf := pools.CopABuffer.Get().(*strings.Builder)
@ -140,21 +140,21 @@ func (pe *Swamp) msgCantGetLock(socksString string, putback bool) {
if putback {
buf.WriteString(", putting back in queue")
}
pe.dbgPrint(buf)
p5.dbgPrint(buf)
}
func (pe *Swamp) msgGotLock(socksString string) {
if !pe.DebugEnabled() {
func (p5 *Swamp) msgGotLock(socksString string) {
if !p5.DebugEnabled() {
return
}
buf := pools.CopABuffer.Get().(*strings.Builder)
buf.WriteString("got lock for ")
buf.WriteString(socksString)
pe.dbgPrint(buf)
p5.dbgPrint(buf)
}
func (pe *Swamp) msgChecked(sock *Proxy, success bool) {
if !pe.DebugEnabled() {
func (p5 *Swamp) msgChecked(sock *Proxy, success bool) {
if !p5.DebugEnabled() {
return
}
buf := pools.CopABuffer.Get().(*strings.Builder)
@ -164,20 +164,20 @@ func (pe *Swamp) msgChecked(sock *Proxy, success bool) {
buf.WriteString(" as ")
buf.WriteString(sock.protocol.Get().String())
buf.WriteString(" proxy")
pe.dbgPrint(buf)
p5.dbgPrint(buf)
return
}
buf.WriteString("failed to verify: ")
buf.WriteString(sock.Endpoint)
pe.dbgPrint(buf)
p5.dbgPrint(buf)
}
func (pe *Swamp) msgBadProxRate(sock *Proxy) {
if !pe.DebugEnabled() {
func (p5 *Swamp) msgBadProxRate(sock *Proxy) {
if !p5.DebugEnabled() {
return
}
buf := pools.CopABuffer.Get().(*strings.Builder)
buf.WriteString("badProx ratelimited: ")
buf.WriteString(sock.Endpoint)
pe.dbgPrint(buf)
p5.dbgPrint(buf)
}

View File

@ -10,58 +10,58 @@ import (
// GetStatistics returns all current statistics.
// * This is a pointer, do not modify it!
func (pe *Swamp) GetStatistics() *statistics {
return pe.stats
func (p5 *Swamp) GetStatistics() *statistics {
return p5.stats
}
// RandomUserAgent retrieves a random user agent from our list in string form.
func (pe *Swamp) RandomUserAgent() string {
pe.mu.RLock()
defer pe.mu.RUnlock()
return entropy.RandomStrChoice(pe.swampopt.userAgents)
func (p5 *Swamp) RandomUserAgent() string {
p5.mu.RLock()
defer p5.mu.RUnlock()
return entropy.RandomStrChoice(p5.swampopt.userAgents)
}
// GetRandomEndpoint returns a random whatismyip style endpoint from our Swamp's options
func (pe *Swamp) GetRandomEndpoint() string {
pe.mu.RLock()
defer pe.mu.RUnlock()
return entropy.RandomStrChoice(pe.swampopt.checkEndpoints)
func (p5 *Swamp) GetRandomEndpoint() string {
p5.mu.RLock()
defer p5.mu.RUnlock()
return entropy.RandomStrChoice(p5.swampopt.checkEndpoints)
}
// GetStaleTime returns the duration of time after which a proxy will be considered "stale".
func (pe *Swamp) GetStaleTime() time.Duration {
pe.swampopt.RLock()
defer pe.swampopt.RLock()
return pe.swampopt.stale
func (p5 *Swamp) GetStaleTime() time.Duration {
p5.swampopt.RLock()
defer p5.swampopt.RLock()
return p5.swampopt.stale
}
// GetValidationTimeout returns the current value of validationTimeout.
func (pe *Swamp) GetValidationTimeout() time.Duration {
pe.swampopt.RLock()
defer pe.swampopt.RLock()
return pe.swampopt.validationTimeout
func (p5 *Swamp) GetValidationTimeout() time.Duration {
p5.swampopt.RLock()
defer p5.swampopt.RLock()
return p5.swampopt.validationTimeout
}
// GetValidationTimeoutStr returns the current value of validationTimeout (in seconds string).
func (pe *Swamp) GetValidationTimeoutStr() string {
pe.swampopt.RLock()
defer pe.swampopt.RLock()
timeout := pe.swampopt.validationTimeout
func (p5 *Swamp) GetValidationTimeoutStr() string {
p5.swampopt.RLock()
defer p5.swampopt.RLock()
timeout := p5.swampopt.validationTimeout
return strconv.Itoa(int(timeout / time.Second))
}
// GetServerTimeout returns the current value of serverTimeout.
func (pe *Swamp) GetServerTimeout() time.Duration {
pe.swampopt.RLock()
defer pe.swampopt.RLock()
return pe.swampopt.serverTimeout
func (p5 *Swamp) GetServerTimeout() time.Duration {
p5.swampopt.RLock()
defer p5.swampopt.RLock()
return p5.swampopt.serverTimeout
}
// GetServerTimeoutStr returns the current value of serverTimeout (in seconds string).
func (pe *Swamp) GetServerTimeoutStr() string {
pe.swampopt.RLock()
defer pe.swampopt.RLock()
timeout := pe.swampopt.serverTimeout
func (p5 *Swamp) GetServerTimeoutStr() string {
p5.swampopt.RLock()
defer p5.swampopt.RLock()
timeout := p5.swampopt.serverTimeout
if timeout == time.Duration(0) {
return "-1"
}
@ -69,58 +69,58 @@ func (pe *Swamp) GetServerTimeoutStr() string {
}
// GetMaxWorkers returns maximum amount of workers that validate proxies concurrently. Note this is read-only during runtime.
func (pe *Swamp) GetMaxWorkers() int {
return pe.pool.Cap()
func (p5 *Swamp) GetMaxWorkers() int {
return p5.pool.Cap()
}
// IsRunning returns true if our background goroutines defined in daemons.go are currently operational
func (pe *Swamp) IsRunning() bool {
return atomic.LoadInt32(&pe.runningdaemons) == 2
func (p5 *Swamp) IsRunning() bool {
return atomic.LoadInt32(&p5.runningdaemons) == 2
}
// GetRecyclingStatus retrieves the current recycling status, see EnableRecycling.
func (pe *Swamp) GetRecyclingStatus() bool {
pe.swampopt.RLock()
defer pe.swampopt.RLock()
return pe.swampopt.recycle
func (p5 *Swamp) GetRecyclingStatus() bool {
p5.swampopt.RLock()
defer p5.swampopt.RLock()
return p5.swampopt.recycle
}
// GetWorkers retrieves pond worker statistics:
// - return MaxWorkers, RunningWorkers, IdleWorkers
func (pe *Swamp) GetWorkers() (maxWorkers, runningWorkers, idleWorkers int) {
pe.mu.RLock()
defer pe.mu.RUnlock()
return pe.pool.Cap(), pe.pool.Running(), pe.pool.Free()
func (p5 *Swamp) GetWorkers() (maxWorkers, runningWorkers, idleWorkers int) {
p5.mu.RLock()
defer p5.mu.RUnlock()
return p5.pool.Cap(), p5.pool.Running(), p5.pool.Free()
}
// GetRemoveAfter retrieves the removeafter policy, the amount of times a recycled proxy is marked as bad until it is removed entirely.
// - returns -1 if recycling is disabled.
func (pe *Swamp) GetRemoveAfter() int {
pe.mu.RLock()
defer pe.mu.RUnlock()
if !pe.swampopt.recycle {
func (p5 *Swamp) GetRemoveAfter() int {
p5.mu.RLock()
defer p5.mu.RUnlock()
if !p5.swampopt.recycle {
return -1
}
return pe.swampopt.removeafter
return p5.swampopt.removeafter
}
// GetDialerBailout retrieves the dialer bailout policy. See SetDialerBailout for more info.
func (pe *Swamp) GetDialerBailout() int {
pe.mu.RLock()
defer pe.mu.RUnlock()
return pe.swampopt.dialerBailout
func (p5 *Swamp) GetDialerBailout() int {
p5.mu.RLock()
defer p5.mu.RUnlock()
return p5.swampopt.dialerBailout
}
// TODO: Document middleware concept
func (pe *Swamp) GetDispenseMiddleware() func(*Proxy) (*Proxy, bool) {
pe.mu.RLock()
defer pe.mu.RUnlock()
return pe.dispenseMiddleware
func (p5 *Swamp) GetDispenseMiddleware() func(*Proxy) (*Proxy, bool) {
p5.mu.RLock()
defer p5.mu.RUnlock()
return p5.dispenseMiddleware
}
func (pe *Swamp) GetShuffleStatus() bool {
pe.mu.RLock()
defer pe.mu.RUnlock()
return pe.swampopt.shuffle
func (p5 *Swamp) GetShuffleStatus() bool {
p5.mu.RLock()
defer p5.mu.RUnlock()
return p5.swampopt.shuffle
}

1
go.mod
View File

@ -10,6 +10,7 @@ require (
github.com/mattn/go-tty v0.0.4
github.com/miekg/dns v1.1.50
github.com/ooni/oohttp v0.3.0
github.com/panjf2000/ants/v2 v2.5.0
github.com/refraction-networking/utls v1.1.2
github.com/yunginnanet/Rate5 v1.1.0
golang.org/x/net v0.0.0-20220921203646-d300de134e69

6
go.sum
View File

@ -6,6 +6,7 @@ git.tcp.direct/kayos/socks v0.0.0-20220828111753-f9f7cd3e7ee7 h1:zuN2VWun3lu34Lz
git.tcp.direct/kayos/socks v0.0.0-20220828111753-f9f7cd3e7ee7/go.mod h1:KmN5oa1od8tMHmRIr9GOqWKx9MR0oGZVtAj+ARxiPwo=
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364 h1:5XxdakFhqd9dnXoAZy1Mb2R/DZ6D1e+0bGC/JhucGYI=
github.com/haxii/socks5 v1.0.0 h1:78BIzd4lHibdRNOKdMwKCnnsgYLW9SeotqU+nMhWSSo=
@ -23,11 +24,15 @@ github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
github.com/ooni/oohttp v0.3.0 h1:75OsZKelkLXl6p2UD53dTJyIv+9owWqaL6sMT26LN8w=
github.com/ooni/oohttp v0.3.0/go.mod h1:fgNDPYw+nsgEKCDBpT/4R06bgnrCRtvgNmAWOCmm4JE=
github.com/panjf2000/ants/v2 v2.5.0 h1:1rWGWSnxCsQBga+nQbA4/iY6VMeNoOIAM0ZWh9u3q2Q=
github.com/panjf2000/ants/v2 v2.5.0/go.mod h1:cU93usDlihJZ5CfRGNDYsiBYvoilLvBF5Qp/BT2GNRE=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/refraction-networking/utls v1.1.2 h1:a7GQauRt72VG+wtNm0lnrAaCGlyX47gEi1++dSsDBpw=
github.com/refraction-networking/utls v1.1.2/go.mod h1:+D89TUtA8+NKVFj1IXWr0p3tSdX1+SqUB7rL0QnGqyg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yunginnanet/Rate5 v1.1.0 h1:FGp+IwKju0cTrrM3VffZGZiFgRt1jFXOWRCPwB1HPek=
@ -88,5 +93,6 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
inet.af/netaddr v0.0.0-20220811202034-502d2d690317 h1:U2fwK6P2EqmopP/hFLTOAjWTki0qgd4GMJn5X8wOleU=
inet.af/netaddr v0.0.0-20220811202034-502d2d690317/go.mod h1:OIezDfdzOgFhuw4HuWapWq2e9l0H9tK4F1j+ETRtF3k=

View File

@ -8,35 +8,26 @@ import (
)
// GetHTTPClient retrieves a pointer to an http.Client powered by MysteryDialer.
func (pe *Swamp) GetHTTPClient() *http.Client {
// var htp func(*http.Request) (*url.URL, error)
func (p5 *Swamp) GetHTTPClient() *http.Client {
var dctx func(ctx context.Context, network string, addr string) (net.Conn, error)
// if httun, htok := pe.GetHTTPTunnel(); htok {
// httprox, uerr := url.Parse("http://" + httun.Endpoint)
// if uerr == nil {
// htp = http.ProxyURL(httprox)
// }
// }
// if htp == nil {
dctx = pe.DialContext
// }
dctx = p5.DialContext
return &http.Client{
Transport: &http.Transport{
// Proxy: htp,
DialContext: dctx,
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
TLSHandshakeTimeout: pe.GetServerTimeout(),
TLSHandshakeTimeout: p5.GetServerTimeout(),
DisableKeepAlives: true,
DisableCompression: false,
MaxIdleConnsPerHost: 5,
IdleConnTimeout: pe.GetServerTimeout(),
ResponseHeaderTimeout: pe.GetServerTimeout(),
IdleConnTimeout: p5.GetServerTimeout(),
ResponseHeaderTimeout: p5.GetServerTimeout(),
},
Timeout: pe.GetServerTimeout(),
Timeout: p5.GetServerTimeout(),
}
}
// RoundTrip is Mr. WorldWide. Obviously. See: https://pkg.go.dev/net/http#RoundTripper
func (pe *Swamp) RoundTrip(req *http.Request) (*http.Response, error) {
return pe.GetHTTPClient().Do(req)
func (p5 *Swamp) RoundTrip(req *http.Request) (*http.Response, error) {
return p5.GetHTTPClient().Do(req)
}

View File

@ -45,7 +45,7 @@ func (p5 *Swamp) addTimeout(socksString string) string {
}
func (p5 *Swamp) popSockAndLockIt(ctx context.Context) (*Proxy, error) {
sock := p5.GetAnySOCKS(false)
sock := p5.GetAnySOCKS()
socksString := sock.String()
select {
case <-ctx.Done():

View File

@ -7,113 +7,113 @@ import (
)
// AddUserAgents appends to the list of useragents we randomly choose from during proxied requests
func (pe *Swamp) AddUserAgents(uagents []string) {
pe.mu.Lock()
defer pe.mu.Unlock()
pe.swampopt.userAgents = append(pe.swampopt.userAgents, uagents...)
func (p5 *Swamp) AddUserAgents(uagents []string) {
p5.mu.Lock()
defer p5.mu.Unlock()
p5.swampopt.userAgents = append(p5.swampopt.userAgents, uagents...)
}
// SetUserAgents sets the list of useragents we randomly choose from during proxied requests
func (pe *Swamp) SetUserAgents(uagents []string) {
pe.mu.Lock()
defer pe.mu.Unlock()
pe.swampopt.userAgents = uagents
func (p5 *Swamp) SetUserAgents(uagents []string) {
p5.mu.Lock()
defer p5.mu.Unlock()
p5.swampopt.userAgents = uagents
}
// SetCheckEndpoints replaces the running list of whatismyip style endpoitns for validation. (must return only the WAN IP)
func (pe *Swamp) SetCheckEndpoints(newendpoints []string) {
pe.mu.Lock()
defer pe.mu.Unlock()
pe.swampopt.checkEndpoints = newendpoints
func (p5 *Swamp) SetCheckEndpoints(newendpoints []string) {
p5.mu.Lock()
defer p5.mu.Unlock()
p5.swampopt.checkEndpoints = newendpoints
}
// AddCheckEndpoints appends entries to the running list of whatismyip style endpoitns for validation. (must return only the WAN IP)
func (pe *Swamp) AddCheckEndpoints(endpoints []string) {
pe.mu.Lock()
defer pe.mu.Unlock()
pe.swampopt.checkEndpoints = append(pe.swampopt.checkEndpoints, endpoints...)
func (p5 *Swamp) AddCheckEndpoints(endpoints []string) {
p5.mu.Lock()
defer p5.mu.Unlock()
p5.swampopt.checkEndpoints = append(p5.swampopt.checkEndpoints, endpoints...)
}
// SetStaleTime replaces the duration of time after which a proxy will be considered "stale". stale proxies will be skipped upon retrieval.
func (pe *Swamp) SetStaleTime(newtime time.Duration) {
pe.swampopt.Lock()
defer pe.swampopt.Unlock()
pe.swampopt.stale = newtime
func (p5 *Swamp) SetStaleTime(newtime time.Duration) {
p5.swampopt.Lock()
defer p5.swampopt.Unlock()
p5.swampopt.stale = newtime
}
// SetValidationTimeout sets the validationTimeout option.
func (pe *Swamp) SetValidationTimeout(timeout time.Duration) {
pe.swampopt.Lock()
defer pe.swampopt.Unlock()
pe.swampopt.validationTimeout = timeout
func (p5 *Swamp) SetValidationTimeout(timeout time.Duration) {
p5.swampopt.Lock()
defer p5.swampopt.Unlock()
p5.swampopt.validationTimeout = timeout
}
// SetServerTimeout sets the serverTimeout option.
// * serverTimeout defines the timeout for outgoing connections made with the MysteryDialer.
// * To disable timeout on outgoing MysteryDialer connections, set this to time.Duration(0).
func (pe *Swamp) SetServerTimeout(timeout time.Duration) {
pe.swampopt.Lock()
defer pe.swampopt.Unlock()
pe.swampopt.serverTimeout = timeout
func (p5 *Swamp) SetServerTimeout(timeout time.Duration) {
p5.swampopt.Lock()
defer p5.swampopt.Unlock()
p5.swampopt.serverTimeout = timeout
}
// SetMaxWorkers set the maximum workers for proxy checking and clears the current proxy map and worker pool jobs.
func (pe *Swamp) SetMaxWorkers(num int) {
pe.pool.Tune(num)
func (p5 *Swamp) SetMaxWorkers(num int) {
p5.pool.Tune(num)
}
// EnableRecycling enables recycling used proxies back into the pending channel for revalidation after dispensed.
func (pe *Swamp) EnableRecycling() {
pe.swampopt.Lock()
defer pe.swampopt.Unlock()
pe.swampopt.recycle = true
func (p5 *Swamp) EnableRecycling() {
p5.swampopt.Lock()
defer p5.swampopt.Unlock()
p5.swampopt.recycle = true
}
// DisableRecycling disables recycling used proxies back into the pending channel for revalidation after dispensed.
func (pe *Swamp) DisableRecycling() {
pe.swampopt.Lock()
defer pe.swampopt.Unlock()
pe.swampopt.recycle = false
func (p5 *Swamp) DisableRecycling() {
p5.swampopt.Lock()
defer p5.swampopt.Unlock()
p5.swampopt.recycle = false
}
// SetRemoveAfter sets the removeafter policy, the amount of times a recycled proxy is marked as bad before it is removed entirely.
// - Default is 10
// - To disable deleting entirely, set this value to -1
// - Only applies when recycling is enabled
func (pe *Swamp) SetRemoveAfter(timesfailed int) {
pe.swampopt.Lock()
defer pe.swampopt.Unlock()
pe.swampopt.removeafter = timesfailed
func (p5 *Swamp) SetRemoveAfter(timesfailed int) {
p5.swampopt.Lock()
defer p5.swampopt.Unlock()
p5.swampopt.removeafter = timesfailed
}
// SetDialerBailout sets the amount of times the MysteryDialer will dial out and fail before it bails out.
// - The dialer will attempt to redial a destination with a different proxy a specified amount of times before it gives up
func (pe *Swamp) SetDialerBailout(dialattempts int) {
pe.swampopt.Lock()
defer pe.swampopt.Unlock()
pe.swampopt.dialerBailout = dialattempts
func (p5 *Swamp) SetDialerBailout(dialattempts int) {
p5.swampopt.Lock()
defer p5.swampopt.Unlock()
p5.swampopt.dialerBailout = dialattempts
}
// SetDispenseMiddleware will add a function that sits within the dialing process of the MysteryDialer and anyhing using it.
// This means this function will be called mid-dial during connections. Return true to approve proxy, false to skip it.
// Take care modiying the proxy in-flight as it is a pointer.
func (pe *Swamp) SetDispenseMiddleware(f func(*Proxy) (*Proxy, bool)) {
pe.mu.Lock()
defer pe.mu.Unlock()
pe.dispenseMiddleware = f
func (p5 *Swamp) SetDispenseMiddleware(f func(*Proxy) (*Proxy, bool)) {
p5.mu.Lock()
defer p5.mu.Unlock()
p5.dispenseMiddleware = f
}
// SetDebugLogger sets the debug logger for the Swamp. See the Logger interface for implementation details.
func (pe *Swamp) SetDebugLogger(l logger.Logger) {
func (p5 *Swamp) SetDebugLogger(l logger.Logger) {
debugHardLock.Lock()
pe.mu.Lock()
pe.DebugLogger = l
pe.mu.Unlock()
p5.mu.Lock()
p5.DebugLogger = l
p5.mu.Unlock()
debugHardLock.Unlock()
}
func (pe *Swamp) SetShuffle(shuffle bool) {
pe.mu.Lock()
defer pe.mu.Unlock()
pe.swampopt.shuffle = shuffle
func (p5 *Swamp) SetShuffle(shuffle bool) {
p5.mu.Lock()
defer p5.mu.Unlock()
p5.swampopt.shuffle = shuffle
}

View File

@ -24,19 +24,19 @@ func (s socksCreds) Valid(username, password string) bool {
// StartSOCKS5Server starts our rotating proxy SOCKS5 server.
// listen is standard Go listen string, e.g: "127.0.0.1:1080".
// username and password are used for authenticatig to the SOCKS5 server.
func (pe *Swamp) StartSOCKS5Server(listen, username, password string) error {
func (p5 *Swamp) StartSOCKS5Server(listen, username, password string) error {
conf := &socks5.Config{
Credentials: socksCreds{username: username, password: password},
Logger: pe.DebugLogger,
Dial: pe.MysteryDialer,
Logger: p5.DebugLogger,
Dial: p5.MysteryDialer,
// Resolver: pe.MysteryResolver,
}
buf := pools.CopABuffer.Get().(*strings.Builder)
buf.WriteString("listening for SOCKS5 connections on ")
buf.WriteString(listen)
pe.dbgPrint(buf)
p5.dbgPrint(buf)
server, err := socks5.New(conf)
if err != nil {

View File

@ -49,8 +49,8 @@ func (stats *statistics) http() {
}
// GetTotalValidated retrieves our grand total validated proxy count.
func (pe *Swamp) GetTotalValidated() int {
stats := pe.GetStatistics()
func (p5 *Swamp) GetTotalValidated() int {
stats := p5.GetStatistics()
return int(stats.Valid4a + stats.Valid4 + stats.Valid5 + stats.ValidHTTP)
}

View File

@ -18,13 +18,13 @@ import (
"git.tcp.direct/kayos/prox5/internal/pools"
)
func (pe *Swamp) prepHTTP() (*http.Client, *http.Transport, *http.Request, error) {
req, err := http.NewRequest("GET", pe.GetRandomEndpoint(), bytes.NewBuffer([]byte("")))
func (p5 *Swamp) prepHTTP() (*http.Client, *http.Transport, *http.Request, error) {
req, err := http.NewRequest("GET", p5.GetRandomEndpoint(), bytes.NewBuffer([]byte("")))
if err != nil {
return nil, nil, nil, err
}
headers := make(map[string]string)
headers["User-Agent"] = pe.RandomUserAgent()
headers["User-Agent"] = p5.RandomUserAgent()
headers["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
headers["Accept-Language"] = "en-US,en;q=0.5"
headers["'Accept-Encoding'"] = "gzip, deflate, br"
@ -36,7 +36,7 @@ func (pe *Swamp) prepHTTP() (*http.Client, *http.Transport, *http.Request, error
var transporter = &http.Transport{
DisableKeepAlives: true,
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, //nolint:gosec
TLSHandshakeTimeout: pe.GetValidationTimeout(),
TLSHandshakeTimeout: p5.GetValidationTimeout(),
}
return client, transporter, req, err
@ -51,13 +51,13 @@ func (sock *Proxy) good() {
sock.lastValidated = time.Now()
}
func (pe *Swamp) bakeHTTP(hmd *HandMeDown) (client *http.Client, req *http.Request, err error) {
func (p5 *Swamp) bakeHTTP(hmd *HandMeDown) (client *http.Client, req *http.Request, err error) {
builder := pools.CopABuffer.Get().(*strings.Builder)
builder.WriteString(hmd.protoCheck.String())
builder.WriteString("://")
builder.WriteString(hmd.sock.Endpoint)
builder.WriteString("/?timeout=")
builder.WriteString(pe.GetValidationTimeoutStr())
builder.WriteString(p5.GetValidationTimeoutStr())
builder.WriteString("s")
dialSocks := socks.DialWithConn(builder.String(), hmd.conn)
pools.DiscardBuffer(builder)
@ -67,7 +67,7 @@ func (pe *Swamp) bakeHTTP(hmd *HandMeDown) (client *http.Client, req *http.Reque
transport *http.Transport
)
if client, transport, req, err = pe.prepHTTP(); err != nil {
if client, transport, req, err = p5.prepHTTP(); err != nil {
return
}
@ -83,14 +83,14 @@ func (pe *Swamp) bakeHTTP(hmd *HandMeDown) (client *http.Client, req *http.Reque
return
}
func (pe *Swamp) validate(hmd *HandMeDown) (string, error) {
func (p5 *Swamp) validate(hmd *HandMeDown) (string, error) {
var (
client *http.Client
req *http.Request
err error
)
client, req, err = pe.bakeHTTP(hmd)
client, req, err = p5.bakeHTTP(hmd)
if err != nil {
return "", err
}
@ -105,8 +105,8 @@ func (pe *Swamp) validate(hmd *HandMeDown) (string, error) {
return string(rbody), err
}
func (pe *Swamp) anothaOne() {
pe.stats.Checked++
func (p5 *Swamp) anothaOne() {
p5.stats.Checked++
}
type HandMeDown struct {
@ -126,28 +126,28 @@ func (hmd *HandMeDown) Dial(network, addr string) (c net.Conn, err error) {
return hmd.conn, nil
}
func (pe *Swamp) singleProxyCheck(sock *Proxy, protocol ProxyProtocol) error {
defer pe.anothaOne()
func (p5 *Swamp) singleProxyCheck(sock *Proxy, protocol ProxyProtocol) error {
defer p5.anothaOne()
split := strings.Split(sock.Endpoint, "@")
endpoint := split[0]
if len(split) == 2 {
endpoint = split[1]
}
conn, err := net.DialTimeout("tcp", endpoint, pe.GetValidationTimeout())
conn, err := net.DialTimeout("tcp", endpoint, p5.GetValidationTimeout())
if err != nil {
return err
}
hmd := &HandMeDown{sock: sock, conn: conn, under: proxy.Direct, protoCheck: protocol}
resp, err := pe.validate(hmd)
resp, err := p5.validate(hmd)
if err != nil {
pe.badProx.Check(sock)
p5.badProx.Check(sock)
return err
}
if newip := net.ParseIP(resp); newip == nil {
pe.badProx.Check(sock)
p5.badProx.Check(sock)
return errors.New("bad response from http request: " + resp)
}
@ -213,20 +213,20 @@ func (sock *Proxy) validate() {
pe.tally(sock)
}
func (pe *Swamp) tally(sock *Proxy) {
func (p5 *Swamp) tally(sock *Proxy) {
switch sock.protocol.Get() {
case ProtoSOCKS4:
pe.stats.v4()
pe.Valids.SOCKS4 <- sock
p5.stats.v4()
p5.Valids.SOCKS4 <- sock
case ProtoSOCKS4a:
pe.stats.v4a()
pe.Valids.SOCKS4a <- sock
p5.stats.v4a()
p5.Valids.SOCKS4a <- sock
case ProtoSOCKS5:
pe.stats.v5()
pe.Valids.SOCKS5 <- sock
p5.stats.v5()
p5.Valids.SOCKS5 <- sock
case ProtoHTTP:
pe.stats.http()
pe.Valids.HTTP <- sock
p5.stats.http()
p5.Valids.HTTP <- sock
default:
return
}