Chore: rename

This commit is contained in:
kayos@tcp.direct 2022-10-16 03:53:04 -07:00
parent 55967117bd
commit 2bdec32e33
Signed by: kayos
GPG Key ID: 4B841471B4BEE979
16 changed files with 204 additions and 186 deletions

View File

@ -6,20 +6,20 @@ import (
"sync/atomic"
)
// SwampStatus represents the current state of our Swamp.
type SwampStatus uint32
// engineState represents the current state of our ProxyEngine.
type engineState uint32
const (
// StateRunning means the proxy pool is currently taking in proxys and validating them, and is available to dispense proxies.
StateRunning SwampStatus = iota
// StatePaused means the proxy pool has been with Swamp.Pause() and may be resumed with Swamp.Resume()
StateRunning engineState = iota
// StatePaused means the proxy pool has been with ProxyEngine.Pause() and may be resumed with ProxyEngine.Resume()
StatePaused
// StateNew means the proxy pool has never been started.
StateNew
)
// Start starts our proxy pool operations. Trying to start a running Swamp will return an error.
func (p5 *Swamp) Start() error {
// Start starts our proxy pool operations. Trying to start a running ProxyEngine will return an error.
func (p5 *ProxyEngine) Start() error {
if atomic.LoadUint32(&p5.Status) != uint32(StateNew) {
return p5.Resume()
}
@ -29,12 +29,12 @@ func (p5 *Swamp) Start() error {
/*
Pause will cease the creation of any new proxy validation operations.
- You will be able to start the proxy pool again with Swamp.Resume(), it will have the same Statistics, options, and ratelimits.
- You will be able to start the proxy pool again with ProxyEngine.Resume(), it will have the same Statistics, options, and ratelimits.
- During pause you are still able to dispense proxies.
- Options may be changed and proxy lists may be loaded when paused.
- Pausing an already paused Swamp is a nonop.
- Pausing an already paused ProxyEngine is a nonop.
*/
func (p5 *Swamp) Pause() error {
func (p5 *ProxyEngine) Pause() error {
if !p5.IsRunning() {
return errors.New("not running")
}
@ -47,13 +47,13 @@ func (p5 *Swamp) Pause() error {
return nil
}
func (p5 *Swamp) startDaemons() {
func (p5 *ProxyEngine) startDaemons() {
go p5.jobSpawner()
atomic.StoreUint32(&p5.Status, uint32(StateRunning))
}
// Resume will resume pause proxy pool operations, attempting to resume a running Swamp is returns an error.
func (p5 *Swamp) Resume() error {
// Resume will resume pause proxy pool operations, attempting to resume a running ProxyEngine is returns an error.
func (p5 *ProxyEngine) Resume() error {
if p5.IsRunning() {
return errors.New("already running")
}

View File

@ -7,13 +7,13 @@ import (
"time"
)
type swampMap struct {
type proxyMap struct {
plot map[string]*Proxy
mu *sync.RWMutex
parent *Swamp
parent *ProxyEngine
}
func (sm swampMap) add(sock string) (*Proxy, bool) {
func (sm proxyMap) add(sock string) (*Proxy, bool) {
sm.mu.Lock()
defer sm.mu.Unlock()
@ -34,14 +34,14 @@ func (sm swampMap) add(sock string) (*Proxy, bool) {
return sm.plot[sock], true
}
func (sm swampMap) exists(sock string) bool {
func (sm proxyMap) exists(sock string) bool {
if _, ok := sm.plot[sock]; !ok {
return false
}
return true
}
func (sm swampMap) delete(sock string) error {
func (sm proxyMap) delete(sock string) error {
sm.mu.Lock()
defer sm.mu.Unlock()
@ -54,7 +54,7 @@ func (sm swampMap) delete(sock string) error {
return nil
}
func (sm swampMap) clear() {
func (sm proxyMap) clear() {
sm.mu.Lock()
defer sm.mu.Unlock()
for key := range sm.plot {
@ -62,21 +62,21 @@ func (sm swampMap) clear() {
}
}
func (p5 *Swamp) recycling() int {
func (p5 *ProxyEngine) recycling() int {
if !p5.GetRecyclingStatus() {
return 0
}
if len(p5.swampmap.plot) < 1 {
if len(p5.proxyMap.plot) < 1 {
return 0
}
var count int
p5.swampmap.mu.RLock()
defer p5.swampmap.mu.RUnlock()
p5.proxyMap.mu.RLock()
defer p5.proxyMap.mu.RUnlock()
for _, sock := range p5.swampmap.plot {
for _, sock := range p5.proxyMap.plot {
select {
case <-p5.ctx.Done():
return 0
@ -90,7 +90,7 @@ func (p5 *Swamp) recycling() int {
return count
}
func (p5 *Swamp) jobSpawner() {
func (p5 *ProxyEngine) jobSpawner() {
if p5.pool.IsClosed() {
p5.pool.Reboot()
}

View File

@ -24,7 +24,7 @@ const (
)
type SocksLogger struct {
parent *Swamp
parent *ProxyEngine
}
// Printf is used to handle socks server logging.
@ -54,20 +54,20 @@ func (b *basicPrinter) Printf(format string, items ...any) {
}
// DebugEnabled returns the current state of our debug switch.
func (p5 *Swamp) DebugEnabled() bool {
func (p5 *ProxyEngine) DebugEnabled() bool {
debugHardLock.RLock()
defer debugHardLock.RUnlock()
return atomic.CompareAndSwapUint32(debugStatus, debugEnabled, debugEnabled)
}
// EnableDebug enables printing of verbose messages during operation
func (p5 *Swamp) EnableDebug() {
func (p5 *ProxyEngine) 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 (p5 *Swamp) DisableDebug() {
func (p5 *ProxyEngine) DisableDebug() {
atomic.StoreUint32(debugStatus, debugDisabled)
}
@ -77,7 +77,7 @@ func simpleString(s string) *pool.String {
return buf
}
func (p5 *Swamp) dbgPrint(builder *pool.String) {
func (p5 *ProxyEngine) dbgPrint(builder *pool.String) {
defer strs.MustPut(builder)
if !p5.DebugEnabled() {
return
@ -86,20 +86,20 @@ func (p5 *Swamp) dbgPrint(builder *pool.String) {
return
}
func (p5 *Swamp) msgUnableToReach(socksString, target string, err error) {
func (p5 *ProxyEngine) msgUnableToReach(socksString, target string, err error) {
if !p5.DebugEnabled() {
return
}
buf := strs.Get()
buf.MustWriteString("unable to reach ")
if p5.swampopt.redact {
if p5.opt.redact {
buf.MustWriteString("[redacted]")
} else {
buf.MustWriteString(target)
}
buf.MustWriteString(" with ")
buf.MustWriteString(socksString)
if !p5.swampopt.redact {
if !p5.opt.redact {
buf.MustWriteString(": ")
buf.MustWriteString(err.Error())
}
@ -107,7 +107,7 @@ func (p5 *Swamp) msgUnableToReach(socksString, target string, err error) {
p5.dbgPrint(buf)
}
func (p5 *Swamp) msgUsingProxy(socksString string) {
func (p5 *ProxyEngine) msgUsingProxy(socksString string) {
if !p5.DebugEnabled() {
return
}
@ -117,7 +117,7 @@ func (p5 *Swamp) msgUsingProxy(socksString string) {
p5.dbgPrint(buf)
}
func (p5 *Swamp) msgFailedMiddleware(socksString string) {
func (p5 *ProxyEngine) msgFailedMiddleware(socksString string) {
if !p5.DebugEnabled() {
return
}
@ -128,7 +128,7 @@ func (p5 *Swamp) msgFailedMiddleware(socksString string) {
p5.dbgPrint(buf)
}
func (p5 *Swamp) msgTry(socksString string) {
func (p5 *ProxyEngine) msgTry(socksString string) {
if !p5.DebugEnabled() {
return
}
@ -138,7 +138,7 @@ func (p5 *Swamp) msgTry(socksString string) {
p5.dbgPrint(buf)
}
func (p5 *Swamp) msgCantGetLock(socksString string, putback bool) {
func (p5 *ProxyEngine) msgCantGetLock(socksString string, putback bool) {
if !p5.DebugEnabled() {
return
}
@ -151,7 +151,7 @@ func (p5 *Swamp) msgCantGetLock(socksString string, putback bool) {
p5.dbgPrint(buf)
}
func (p5 *Swamp) msgGotLock(socksString string) {
func (p5 *ProxyEngine) msgGotLock(socksString string) {
if !p5.DebugEnabled() {
return
}
@ -161,7 +161,7 @@ func (p5 *Swamp) msgGotLock(socksString string) {
p5.dbgPrint(buf)
}
func (p5 *Swamp) msgChecked(sock *Proxy, success bool) {
func (p5 *ProxyEngine) msgChecked(sock *Proxy, success bool) {
if !p5.DebugEnabled() {
return
}
@ -180,7 +180,7 @@ func (p5 *Swamp) msgChecked(sock *Proxy, success bool) {
p5.dbgPrint(buf)
}
func (p5 *Swamp) msgBadProxRate(sock *Proxy) {
func (p5 *ProxyEngine) msgBadProxRate(sock *Proxy) {
if !p5.DebugEnabled() {
return
}
@ -202,7 +202,7 @@ var (
// Make sure you pull from the channel eventually to avoid build up of blocked goroutines.
//
// Deprecated: use DebugLogger instead. This will be removed in a future version.
func (p5 *Swamp) DebugChannel() chan string {
func (p5 *ProxyEngine) DebugChannel() chan string {
debugChan = make(chan string, 100)
useDebugChannel = true
return debugChan

56
defs.go
View File

@ -9,6 +9,7 @@ import (
"github.com/panjf2000/ants/v2"
rl "github.com/yunginnanet/Rate5"
"git.tcp.direct/kayos/prox5/internal/scaler"
"git.tcp.direct/kayos/prox5/logger"
)
@ -23,12 +24,12 @@ type ProxyChannels struct {
HTTP chan *Proxy
}
// Swamp represents a proxy pool
type Swamp struct {
// ProxyEngine represents a proxy pool
type ProxyEngine struct {
Valids ProxyChannels
DebugLogger logger.Logger
// stats holds the Statistics for our swamp
// stats holds the Statistics for ProxyEngine
stats *Statistics
Status uint32
@ -42,16 +43,19 @@ type Swamp struct {
dispenseMiddleware func(*Proxy) (*Proxy, bool)
ctx context.Context
quit context.CancelFunc
conCtx context.Context
killConns context.CancelFunc
ctx context.Context
quit context.CancelFunc
swampmap swampMap
proxyMap proxyMap
// reaper sync.Pool
mu *sync.RWMutex
pool *ants.Pool
swampopt *config
scaler *scaler.AutoScaler
opt *config
runningdaemons int32
conductor chan bool
}
@ -96,7 +100,7 @@ func defOpt() *config {
return sm
}
// config holds our configuration for Swamp instances.
// config holds our configuration for ProxyEngine instances.
// This is implemented as a pointer, and should be interacted with via the setter and getter functions.
type config struct {
// stale is the amount of time since verification that qualifies a proxy going stale.
@ -133,21 +137,28 @@ type config struct {
*sync.RWMutex
}
// NewDefaultSwamp returns a new Swamp instance.
// NewDefaultSwamp returns a new ProxyEngine instance.
//
// Deprecated: use NewProxyEngine instead.
func NewDefaultSwamp() *Swamp {
return NewProxyEngine()
return &Swamp{NewProxyEngine()}
}
// NewProxyEngine returns a Swamp with default options.
// After calling this you may use the various "setters" to change the options before calling Swamp.Start().
func NewProxyEngine() *Swamp {
pe := &Swamp{
// Swamp is a deprecated alias for ProxyEngine
//
// Deprecated: use ProxyEngine instead.
type Swamp struct {
*ProxyEngine
}
// NewProxyEngine returns a ProxyEngine with default options.
// After calling this you may use the various "setters" to change the options before calling ProxyEngine.Start().
func NewProxyEngine() *ProxyEngine {
pe := &ProxyEngine{
stats: &Statistics{birthday: time.Now()},
DebugLogger: &basicPrinter{},
swampopt: defOpt(),
opt: defOpt(),
conductor: make(chan bool),
mu: &sync.RWMutex{},
@ -168,16 +179,17 @@ func NewProxyEngine() *Swamp {
return p, true
}
pe.ctx, pe.quit = context.WithCancel(context.Background())
pe.swampmap = newSwampMap(pe)
pe.conCtx, pe.killConns = context.WithCancel(context.Background())
pe.proxyMap = newProxyMap(pe)
atomic.StoreUint32(&pe.Status, uint32(StateNew))
atomic.StoreInt32(&pe.runningdaemons, 0)
pe.useProx = rl.NewCustomLimiter(pe.swampopt.useProxConfig)
pe.badProx = rl.NewCustomLimiter(pe.swampopt.badProxConfig)
pe.useProx = rl.NewCustomLimiter(pe.opt.useProxConfig)
pe.badProx = rl.NewCustomLimiter(pe.opt.badProxConfig)
var err error
pe.pool, err = ants.NewPool(pe.swampopt.maxWorkers, ants.WithOptions(ants.Options{
pe.pool, err = ants.NewPool(pe.opt.maxWorkers, ants.WithOptions(ants.Options{
ExpiryDuration: 2 * time.Minute,
PanicHandler: pe.pondPanic,
}))
@ -193,15 +205,15 @@ func NewProxyEngine() *Swamp {
return pe
}
func newSwampMap(pe *Swamp) swampMap {
return swampMap{
func newProxyMap(pe *ProxyEngine) proxyMap {
return proxyMap{
plot: make(map[string]*Proxy),
mu: &sync.RWMutex{},
parent: pe,
}
}
func (p5 *Swamp) pondPanic(p interface{}) {
func (p5 *ProxyEngine) pondPanic(p interface{}) {
panic(p)
// pe.dbgPrint("Worker panic: " + fmt.Sprintf("%v", p))
}

View File

@ -7,7 +7,7 @@ import (
// Socks5Str gets a SOCKS5 proxy that we have fully verified (dialed and then retrieved our IP address from a what-is-my-ip endpoint.
// Will block if one is not available!
func (p5 *Swamp) Socks5Str() string {
func (p5 *ProxyEngine) Socks5Str() string {
for {
select {
case sock := <-p5.Valids.SOCKS5:
@ -24,7 +24,7 @@ func (p5 *Swamp) Socks5Str() string {
// Socks4Str gets a SOCKS4 proxy that we have fully verified.
// Will block if one is not available!
func (p5 *Swamp) Socks4Str() string {
func (p5 *ProxyEngine) Socks4Str() string {
defer p5.stats.dispense()
for {
select {
@ -41,7 +41,7 @@ func (p5 *Swamp) Socks4Str() string {
// Socks4aStr gets a SOCKS4 proxy that we have fully verified.
// Will block if one is not available!
func (p5 *Swamp) Socks4aStr() string {
func (p5 *ProxyEngine) Socks4aStr() string {
defer p5.stats.dispense()
for {
select {
@ -60,7 +60,7 @@ func (p5 *Swamp) Socks4aStr() string {
// For now, this function does not loop forever like the GetAnySOCKS does.
// Alternatively it can be included within the for loop by passing true to GetAnySOCKS.
// If there is an HTTP proxy available, ok will be true. If not, it will return false without delay.
func (p5 *Swamp) GetHTTPTunnel() (p *Proxy, ok bool) {
func (p5 *ProxyEngine) GetHTTPTunnel() (p *Proxy, ok bool) {
select {
case httptunnel := <-p5.Valids.HTTP:
return httptunnel, true
@ -71,7 +71,8 @@ func (p5 *Swamp) GetHTTPTunnel() (p *Proxy, ok bool) {
// GetAnySOCKS retrieves any version SOCKS proxy as a Proxy type
// Will block if one is not available!
func (p5 *Swamp) GetAnySOCKS() *Proxy {
func (p5 *ProxyEngine) GetAnySOCKS() *Proxy {
defer p5.stats.dispense()
for {
var sock *Proxy
@ -92,7 +93,7 @@ func (p5 *Swamp) GetAnySOCKS() *Proxy {
}
}
func (p5 *Swamp) stillGood(sock *Proxy) bool {
func (p5 *ProxyEngine) stillGood(sock *Proxy) bool {
if sock == nil {
return false
}
@ -106,7 +107,7 @@ func (p5 *Swamp) stillGood(sock *Proxy) bool {
buf.MustWriteString("deleting from map (too many failures): ")
buf.MustWriteString(sock.Endpoint)
p5.dbgPrint(buf)
if err := p5.swampmap.delete(sock.Endpoint); err != nil {
if err := p5.proxyMap.delete(sock.Endpoint); err != nil {
p5.dbgPrint(simpleString(err.Error()))
}
}
@ -119,7 +120,7 @@ func (p5 *Swamp) stillGood(sock *Proxy) bool {
return false
}
if time.Since(sock.lastValidated) > p5.swampopt.stale {
if time.Since(sock.lastValidated) > p5.opt.stale {
buf := strs.Get()
buf.MustWriteString("proxy stale: ")
buf.MustWriteString(sock.Endpoint)

View File

@ -47,7 +47,7 @@ func StartUpstreamProxy(listen string) {
func init() {
quit = make(chan bool)
swamp = prox5.NewProxyEngine()
swamp = prox5.NewDefaultSwamp()
swamp.SetMaxWorkers(5)
swamp.EnableDebug()
go StartUpstreamProxy("127.0.0.1:1555")

View File

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

View File

@ -16,7 +16,7 @@ import (
// - yeet.com:1080:user:pass
// - [fe80::2ef0:5dff:fe7f:c299]:1080
// - [fe80::2ef0:5dff:fe7f:c299]:1080:user:pass
func (p5 *Swamp) LoadProxyTXT(seedFile string) (count int) {
func (p5 *ProxyEngine) LoadProxyTXT(seedFile string) (count int) {
f, err := os.Open(seedFile)
if err != nil {
p5.dbgPrint(simpleString(err.Error()))
@ -47,7 +47,7 @@ func (p5 *Swamp) LoadProxyTXT(seedFile string) (count int) {
// - yeet.com:1080:user:pass
// - [fe80::2ef0:5dff:fe7f:c299]:1080
// - [fe80::2ef0:5dff:fe7f:c299]:1080:user:pass
func (p5 *Swamp) LoadSingleProxy(sock string) bool {
func (p5 *ProxyEngine) LoadSingleProxy(sock string) bool {
var ok bool
if sock, ok = filter(sock); !ok {
return false
@ -58,8 +58,8 @@ func (p5 *Swamp) LoadSingleProxy(sock string) bool {
return true
}
func (p5 *Swamp) loadSingleProxy(sock string) error {
if _, ok := p5.swampmap.add(sock); !ok {
func (p5 *ProxyEngine) loadSingleProxy(sock string) error {
if _, ok := p5.proxyMap.add(sock); !ok {
return errors.New("proxy already exists")
}
return nil
@ -73,7 +73,7 @@ func (p5 *Swamp) loadSingleProxy(sock string) error {
// - yeet.com:1080:user:pass
// - [fe80::2ef0:5dff:fe7f:c299]:1080
// - [fe80::2ef0:5dff:fe7f:c299]:1080:user:pass
func (p5 *Swamp) LoadMultiLineString(socks string) int {
func (p5 *ProxyEngine) LoadMultiLineString(socks string) int {
var count int
scan := bufio.NewScanner(strings.NewReader(socks))
for scan.Scan() {
@ -87,6 +87,6 @@ func (p5 *Swamp) LoadMultiLineString(socks string) int {
// ClearSOCKSList clears the map of proxies that we have on record.
// Other operations (proxies that are still in buffered channels) will continue.
func (p5 *Swamp) ClearSOCKSList() {
p5.swampmap.clear()
func (p5 *ProxyEngine) ClearSOCKSList() {
p5.proxyMap.clear()
}

View File

@ -8,7 +8,7 @@ import (
)
// GetHTTPClient retrieves a pointer to an http.Client powered by MysteryDialer.
func (p5 *Swamp) GetHTTPClient() *http.Client {
func (p5 *ProxyEngine) GetHTTPClient() *http.Client {
var dctx func(ctx context.Context, network string, addr string) (net.Conn, error)
dctx = p5.DialContext
return &http.Client{
@ -28,6 +28,6 @@ func (p5 *Swamp) GetHTTPClient() *http.Client {
}
// RoundTrip is Mr. WorldWide. Obviously. See: https://pkg.go.dev/net/http#RoundTripper
func (p5 *Swamp) RoundTrip(req *http.Request) (*http.Response, error) {
func (p5 *ProxyEngine) RoundTrip(req *http.Request) (*http.Response, error) {
return p5.GetHTTPClient().Do(req)
}

View File

@ -11,17 +11,17 @@ import (
)
// DialContext is a simple stub adapter to implement a net.Dialer.
func (p5 *Swamp) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
func (p5 *ProxyEngine) DialContext(ctx context.Context, network, addr string) (net.Conn, error) {
return p5.MysteryDialer(ctx, network, addr)
}
// Dial is a simple stub adapter to implement a net.Dialer.
func (p5 *Swamp) Dial(network, addr string) (net.Conn, error) {
func (p5 *ProxyEngine) Dial(network, addr string) (net.Conn, error) {
return p5.MysteryDialer(context.Background(), network, addr)
}
// DialTimeout is a simple stub adapter to implement a net.Dialer with a timeout.
func (p5 *Swamp) DialTimeout(network, addr string, timeout time.Duration) (net.Conn, error) {
func (p5 *ProxyEngine) DialTimeout(network, addr string, timeout time.Duration) (net.Conn, error) {
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(timeout))
go func() { // this is a goroutine that calls cancel() upon the deadline expiring to avoid context leaks
<-ctx.Done()
@ -30,7 +30,7 @@ func (p5 *Swamp) DialTimeout(network, addr string, timeout time.Duration) (net.C
return p5.MysteryDialer(ctx, network, addr)
}
func (p5 *Swamp) addTimeout(socksString string) string {
func (p5 *ProxyEngine) addTimeout(socksString string) string {
tout := strs.Get()
tout.MustWriteString(socksString)
tout.MustWriteString("?timeout=")
@ -41,30 +41,29 @@ func (p5 *Swamp) addTimeout(socksString string) string {
return socksString
}
func (p5 *Swamp) popSockAndLockIt(ctx context.Context) (*Proxy, error) {
func (p5 *ProxyEngine) popSockAndLockIt(ctx context.Context) (*Proxy, error) {
sock := p5.GetAnySOCKS()
socksString := sock.String()
select {
case <-ctx.Done():
return nil, fmt.Errorf("context done: %w", ctx.Err())
default:
if atomic.CompareAndSwapUint32(&sock.lock, stateUnlocked, stateLocked) {
p5.msgGotLock(socksString)
// p5.msgGotLock(socksString)
return sock, nil
}
select {
case p5.Pending <- sock:
p5.msgCantGetLock(socksString, true)
// p5.msgCantGetLock(socksString, true)
return nil, nil
default:
p5.msgCantGetLock(socksString, false)
p5.msgCantGetLock(sock.String(), false)
return nil, nil
}
}
}
// MysteryDialer is a dialer function that will use a different proxy for every request.
func (p5 *Swamp) MysteryDialer(ctx context.Context, network, addr string) (net.Conn, error) {
func (p5 *ProxyEngine) MysteryDialer(ctx context.Context, network, addr string) (net.Conn, error) {
// pull down proxies from channel until we get a proxy good enough for our spoiled asses
var count = 0
for {
@ -75,6 +74,9 @@ func (p5 *Swamp) MysteryDialer(ctx context.Context, network, addr string) (net.C
if err := ctx.Err(); err != nil {
return nil, fmt.Errorf("context error: %w", err)
}
if p5.conCtx.Err() != nil {
return nil, fmt.Errorf("context closed")
}
var sock *Proxy
for {
var err error

View File

@ -12,7 +12,7 @@ type dnsCacheEntry []netaddr.IP
var dnsCache = make(map[string]dnsCacheEntry)
func (pe *Swamp) Resolve(ctx context.Context, name string) (context.Context, net.IP, error) {
func (pe *ProxyEngine) Resolve(ctx context.Context, name string) (context.Context, net.IP, error) {
var result net.IP
for {
select {

View File

@ -37,7 +37,7 @@ type Proxy struct {
// timesBad is the amount of times the proxy has been marked as bad.
timesBad int64
parent *Swamp
parent *ProxyEngine
lock uint32
}

View File

@ -7,104 +7,104 @@ import (
)
// AddUserAgents appends to the list of useragents we randomly choose from during proxied requests
func (p5 *Swamp) AddUserAgents(uagents []string) {
func (p5 *ProxyEngine) AddUserAgents(uagents []string) {
p5.mu.Lock()
p5.swampopt.userAgents = append(p5.swampopt.userAgents, uagents...)
p5.opt.userAgents = append(p5.opt.userAgents, uagents...)
p5.mu.Unlock()
}
// SetUserAgents sets the list of useragents we randomly choose from during proxied requests
func (p5 *Swamp) SetUserAgents(uagents []string) {
func (p5 *ProxyEngine) SetUserAgents(uagents []string) {
p5.mu.Lock()
p5.swampopt.userAgents = uagents
p5.opt.userAgents = uagents
p5.mu.Unlock()
}
// SetCheckEndpoints replaces the running list of whatismyip style endpoitns for validation. (must return only the WAN IP)
func (p5 *Swamp) SetCheckEndpoints(newendpoints []string) {
func (p5 *ProxyEngine) SetCheckEndpoints(newendpoints []string) {
p5.mu.Lock()
p5.swampopt.checkEndpoints = newendpoints
p5.opt.checkEndpoints = newendpoints
p5.mu.Unlock()
}
// AddCheckEndpoints appends entries to the running list of whatismyip style endpoitns for validation. (must return only the WAN IP)
func (p5 *Swamp) AddCheckEndpoints(endpoints []string) {
func (p5 *ProxyEngine) AddCheckEndpoints(endpoints []string) {
p5.mu.Lock()
p5.swampopt.checkEndpoints = append(p5.swampopt.checkEndpoints, endpoints...)
p5.opt.checkEndpoints = append(p5.opt.checkEndpoints, endpoints...)
p5.mu.Unlock()
}
// SetStaleTime replaces the duration of time after which a proxy will be considered "stale". stale proxies will be skipped upon retrieval.
func (p5 *Swamp) SetStaleTime(newtime time.Duration) {
p5.swampopt.Lock()
p5.swampopt.stale = newtime
p5.swampopt.Unlock()
func (p5 *ProxyEngine) SetStaleTime(newtime time.Duration) {
p5.opt.Lock()
p5.opt.stale = newtime
p5.opt.Unlock()
}
// SetValidationTimeout sets the validationTimeout option.
func (p5 *Swamp) SetValidationTimeout(timeout time.Duration) {
p5.swampopt.Lock()
p5.swampopt.validationTimeout = timeout
p5.swampopt.Unlock()
func (p5 *ProxyEngine) SetValidationTimeout(timeout time.Duration) {
p5.opt.Lock()
p5.opt.validationTimeout = timeout
p5.opt.Unlock()
}
// 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 (p5 *Swamp) SetServerTimeout(timeout time.Duration) {
p5.swampopt.Lock()
p5.swampopt.serverTimeout = timeout
p5.swampopt.Unlock()
func (p5 *ProxyEngine) SetServerTimeout(timeout time.Duration) {
p5.opt.Lock()
p5.opt.serverTimeout = timeout
p5.opt.Unlock()
}
// SetMaxWorkers set the maximum workers for proxy checking and clears the current proxy map and worker pool jobs.
func (p5 *Swamp) SetMaxWorkers(num int) {
func (p5 *ProxyEngine) SetMaxWorkers(num int) {
p5.pool.Tune(num)
}
// EnableRecycling enables recycling used proxies back into the pending channel for revalidation after dispensed.
func (p5 *Swamp) EnableRecycling() {
p5.swampopt.Lock()
p5.swampopt.recycle = true
p5.swampopt.Unlock()
func (p5 *ProxyEngine) EnableRecycling() {
p5.opt.Lock()
p5.opt.recycle = true
p5.opt.Unlock()
}
// DisableRecycling disables recycling used proxies back into the pending channel for revalidation after dispensed.
func (p5 *Swamp) DisableRecycling() {
p5.swampopt.Lock()
p5.swampopt.recycle = false
p5.swampopt.Unlock()
func (p5 *ProxyEngine) DisableRecycling() {
p5.opt.Lock()
p5.opt.recycle = false
p5.opt.Unlock()
}
// 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 (p5 *Swamp) SetRemoveAfter(timesfailed int) {
p5.swampopt.Lock()
p5.swampopt.removeafter = timesfailed
p5.swampopt.Unlock()
func (p5 *ProxyEngine) SetRemoveAfter(timesfailed int) {
p5.opt.Lock()
p5.opt.removeafter = timesfailed
p5.opt.Unlock()
}
// 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 (p5 *Swamp) SetDialerBailout(dialattempts int) {
p5.swampopt.Lock()
p5.swampopt.dialerBailout = dialattempts
p5.swampopt.Unlock()
func (p5 *ProxyEngine) SetDialerBailout(dialattempts int) {
p5.opt.Lock()
p5.opt.dialerBailout = dialattempts
p5.opt.Unlock()
}
// 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 (p5 *Swamp) SetDispenseMiddleware(f func(*Proxy) (*Proxy, bool)) {
func (p5 *ProxyEngine) SetDispenseMiddleware(f func(*Proxy) (*Proxy, bool)) {
p5.mu.Lock()
p5.dispenseMiddleware = f
p5.mu.Unlock()
}
// SetDebugLogger sets the debug logger for the Swamp. See the Logger interface for implementation details.
func (p5 *Swamp) SetDebugLogger(l logger.Logger) {
// SetDebugLogger sets the debug logger for the ProxyEngine. See the Logger interface for implementation details.
func (p5 *ProxyEngine) SetDebugLogger(l logger.Logger) {
debugHardLock.Lock()
p5.mu.Lock()
p5.DebugLogger = l
@ -112,8 +112,8 @@ func (p5 *Swamp) SetDebugLogger(l logger.Logger) {
debugHardLock.Unlock()
}
func (p5 *Swamp) SetShuffle(shuffle bool) {
p5.swampopt.Lock()
p5.swampopt.shuffle = shuffle
p5.swampopt.Unlock()
func (p5 *ProxyEngine) SetShuffle(shuffle bool) {
p5.opt.Lock()
p5.opt.shuffle = shuffle
p5.opt.Unlock()
}

View File

@ -24,7 +24,7 @@ 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 (p5 *Swamp) StartSOCKS5Server(listen, username, password string) error {
func (p5 *ProxyEngine) StartSOCKS5Server(listen, username, password string) error {
conf := &socks5.Config{
Credentials: socksCreds{username: username, password: password},

View File

@ -4,7 +4,7 @@ import (
"time"
)
// Statistics is used to encapsulate various swampy stats
// Statistics is used to encapsulate various proxy engine stats
type Statistics struct {
// Valid4 is the amount of SOCKS4 proxies validated
Valid4 int64
@ -49,7 +49,7 @@ func (stats *Statistics) http() {
}
// GetTotalValidated retrieves our grand total validated proxy count.
func (p5 *Swamp) GetTotalValidated() int {
func (p5 *ProxyEngine) GetTotalValidated() int {
stats := p5.GetStatistics()
return int(stats.Valid4a + stats.Valid4 + stats.Valid5 + stats.ValidHTTP)
}

View File

@ -16,7 +16,7 @@ import (
"golang.org/x/net/proxy"
)
func (p5 *Swamp) prepHTTP() (*http.Client, *http.Transport, *http.Request, error) {
func (p5 *ProxyEngine) 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
@ -49,7 +49,7 @@ func (sock *Proxy) good() {
sock.lastValidated = time.Now()
}
func (p5 *Swamp) bakeHTTP(hmd *HandMeDown) (client *http.Client, req *http.Request, err error) {
func (p5 *ProxyEngine) bakeHTTP(hmd *HandMeDown) (client *http.Client, req *http.Request, err error) {
builder := strs.Get()
builder.MustWriteString(hmd.protoCheck.String())
builder.MustWriteString("://")
@ -81,7 +81,7 @@ func (p5 *Swamp) bakeHTTP(hmd *HandMeDown) (client *http.Client, req *http.Reque
return
}
func (p5 *Swamp) validate(hmd *HandMeDown) (string, error) {
func (p5 *ProxyEngine) validate(hmd *HandMeDown) (string, error) {
var (
client *http.Client
req *http.Request
@ -103,7 +103,7 @@ func (p5 *Swamp) validate(hmd *HandMeDown) (string, error) {
return string(rbody), err
}
func (p5 *Swamp) anothaOne() {
func (p5 *ProxyEngine) anothaOne() {
p5.stats.Checked++
}
@ -124,7 +124,7 @@ func (hmd *HandMeDown) Dial(network, addr string) (c net.Conn, err error) {
return hmd.conn, nil
}
func (p5 *Swamp) singleProxyCheck(sock *Proxy, protocol ProxyProtocol) error {
func (p5 *ProxyEngine) singleProxyCheck(sock *Proxy, protocol ProxyProtocol) error {
defer p5.anothaOne()
split := strings.Split(sock.Endpoint, "@")
endpoint := split[0]
@ -177,6 +177,9 @@ func (sock *Proxy) validate() {
if sock.timesValidated == 0 || sock.protocol.Get() == ProtoNull {
// try to use the proxy with all 3 SOCKS versions
for tryProto := range protoMap {
if tryProto == ProtoNull {
continue
}
select {
case <-pe.ctx.Done():
return
@ -211,7 +214,7 @@ func (sock *Proxy) validate() {
pe.tally(sock)
}
func (p5 *Swamp) tally(sock *Proxy) bool {
func (p5 *ProxyEngine) tally(sock *Proxy) bool {
var target chan *Proxy
switch sock.protocol.Get() {
case ProtoSOCKS4: