2022-05-23 01:05:50 +00:00
|
|
|
package prox5
|
2021-09-20 07:05:21 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"sync/atomic"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
2023-01-31 09:21:29 +00:00
|
|
|
func (p5 *ProxyEngine) getSocksStr(proto ProxyProtocol) string {
|
|
|
|
var sock *Proxy
|
|
|
|
var list *proxyList
|
|
|
|
switch proto {
|
|
|
|
case ProtoSOCKS4:
|
|
|
|
list = &p5.Valids.SOCKS4
|
|
|
|
case ProtoSOCKS4a:
|
|
|
|
list = &p5.Valids.SOCKS4a
|
|
|
|
case ProtoSOCKS5:
|
|
|
|
list = &p5.Valids.SOCKS5
|
|
|
|
case ProtoHTTP:
|
|
|
|
list = &p5.Valids.HTTP
|
|
|
|
}
|
2021-09-20 07:05:21 +00:00
|
|
|
for {
|
2023-01-31 09:21:29 +00:00
|
|
|
if list.Len() == 0 {
|
|
|
|
p5.recycling()
|
|
|
|
time.Sleep(250 * time.Millisecond)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
list.Lock()
|
|
|
|
sock = list.Remove(list.Front()).(*Proxy)
|
|
|
|
list.Unlock()
|
|
|
|
switch {
|
|
|
|
case sock == nil:
|
|
|
|
p5.recycling()
|
|
|
|
time.Sleep(250 * time.Millisecond)
|
|
|
|
continue
|
|
|
|
case !p5.stillGood(sock):
|
|
|
|
sock = nil
|
|
|
|
continue
|
|
|
|
default:
|
2022-09-22 23:45:15 +00:00
|
|
|
p5.stats.dispense()
|
2021-09-20 07:05:21 +00:00
|
|
|
return sock.Endpoint
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-31 09:21:29 +00:00
|
|
|
// 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 *ProxyEngine) Socks5Str() string {
|
|
|
|
return p5.getSocksStr(ProtoSOCKS5)
|
|
|
|
}
|
|
|
|
|
2021-09-20 07:05:21 +00:00
|
|
|
// Socks4Str gets a SOCKS4 proxy that we have fully verified.
|
|
|
|
// Will block if one is not available!
|
2022-10-16 10:53:04 +00:00
|
|
|
func (p5 *ProxyEngine) Socks4Str() string {
|
2023-01-31 09:21:29 +00:00
|
|
|
return p5.getSocksStr(ProtoSOCKS4)
|
2021-09-20 07:05:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Socks4aStr gets a SOCKS4 proxy that we have fully verified.
|
|
|
|
// Will block if one is not available!
|
2022-10-16 10:53:04 +00:00
|
|
|
func (p5 *ProxyEngine) Socks4aStr() string {
|
2023-01-31 09:21:29 +00:00
|
|
|
return p5.getSocksStr(ProtoSOCKS4a)
|
2021-09-20 07:05:21 +00:00
|
|
|
}
|
|
|
|
|
2022-05-23 01:20:40 +00:00
|
|
|
// GetHTTPTunnel checks for an available HTTP CONNECT proxy in our pool.
|
2023-01-31 09:21:29 +00:00
|
|
|
func (p5 *ProxyEngine) GetHTTPTunnel() string {
|
|
|
|
return p5.getSocksStr(ProtoHTTP)
|
2022-05-23 01:20:40 +00:00
|
|
|
}
|
|
|
|
|
2021-09-20 07:05:21 +00:00
|
|
|
// GetAnySOCKS retrieves any version SOCKS proxy as a Proxy type
|
|
|
|
// Will block if one is not available!
|
2022-10-16 10:53:04 +00:00
|
|
|
func (p5 *ProxyEngine) GetAnySOCKS() *Proxy {
|
2023-01-31 09:21:29 +00:00
|
|
|
var sock *Proxy
|
2022-09-22 23:45:15 +00:00
|
|
|
defer p5.stats.dispense()
|
2023-01-31 09:21:29 +00:00
|
|
|
|
2021-09-20 07:05:21 +00:00
|
|
|
for {
|
|
|
|
select {
|
2023-01-31 09:21:29 +00:00
|
|
|
case <-p5.ctx.Done():
|
|
|
|
return nil
|
2021-09-20 07:05:21 +00:00
|
|
|
default:
|
2023-01-31 09:21:29 +00:00
|
|
|
//
|
2021-09-20 07:05:21 +00:00
|
|
|
}
|
2023-01-31 09:21:29 +00:00
|
|
|
for _, list := range p5.Valids.Slice() {
|
|
|
|
list.RLock()
|
|
|
|
if list.Len() > 0 {
|
|
|
|
list.RUnlock()
|
|
|
|
sock = list.pop()
|
|
|
|
switch {
|
|
|
|
case sock == nil:
|
|
|
|
p5.recycling()
|
|
|
|
time.Sleep(50 * time.Millisecond)
|
|
|
|
case p5.stillGood(sock):
|
|
|
|
return sock
|
|
|
|
default:
|
|
|
|
sock = nil
|
|
|
|
}
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
list.RUnlock()
|
2021-09-20 07:05:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-16 10:53:04 +00:00
|
|
|
func (p5 *ProxyEngine) stillGood(sock *Proxy) bool {
|
2022-08-28 16:37:40 +00:00
|
|
|
if sock == nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if !atomic.CompareAndSwapUint32(&sock.lock, stateUnlocked, stateLocked) {
|
|
|
|
return false
|
2021-09-20 07:05:21 +00:00
|
|
|
}
|
|
|
|
defer atomic.StoreUint32(&sock.lock, stateUnlocked)
|
|
|
|
|
2023-01-28 03:59:28 +00:00
|
|
|
if p5.GetRemoveAfter() != -1 && atomic.LoadInt64(&sock.timesBad) > int64(p5.GetRemoveAfter()) {
|
2022-10-16 06:45:19 +00:00
|
|
|
buf := strs.Get()
|
|
|
|
buf.MustWriteString("deleting from map (too many failures): ")
|
|
|
|
buf.MustWriteString(sock.Endpoint)
|
2022-09-22 23:45:15 +00:00
|
|
|
p5.dbgPrint(buf)
|
2022-10-16 10:53:04 +00:00
|
|
|
if err := p5.proxyMap.delete(sock.Endpoint); err != nil {
|
2022-09-22 23:45:15 +00:00
|
|
|
p5.dbgPrint(simpleString(err.Error()))
|
2021-09-20 08:49:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-22 23:45:15 +00:00
|
|
|
if p5.badProx.Peek(sock) {
|
2022-10-16 06:45:19 +00:00
|
|
|
buf := strs.Get()
|
|
|
|
buf.MustWriteString("badProx dial ratelimited: ")
|
|
|
|
buf.MustWriteString(sock.Endpoint)
|
2022-09-22 23:45:15 +00:00
|
|
|
p5.dbgPrint(buf)
|
2021-09-20 07:05:21 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2022-10-16 10:53:04 +00:00
|
|
|
if time.Since(sock.lastValidated) > p5.opt.stale {
|
2022-10-16 06:45:19 +00:00
|
|
|
buf := strs.Get()
|
|
|
|
buf.MustWriteString("proxy stale: ")
|
|
|
|
buf.MustWriteString(sock.Endpoint)
|
2022-09-22 23:45:15 +00:00
|
|
|
p5.dbgPrint(buf)
|
2023-01-31 09:21:29 +00:00
|
|
|
p5.stats.stale()
|
2021-09-20 07:05:21 +00:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|