mirror of
https://github.com/qdm12/gluetun.git
synced 2026-06-10 06:12:27 +02:00
eb9916f0ac
- `SOCKS5_ENABLED=off` - `SOCKS5_LISTENING_ADDRESS=":1080"` - `SOCKS5_USER=` - `SOCKS5_PASSWORD=`
107 lines
1.8 KiB
Go
107 lines
1.8 KiB
Go
package socks5
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/qdm12/goservices"
|
|
)
|
|
|
|
type Loop struct {
|
|
settings Settings
|
|
|
|
mutex sync.Mutex
|
|
runCancel context.CancelFunc
|
|
runDone <-chan error
|
|
}
|
|
|
|
func NewLoop(settings Settings) *Loop {
|
|
return &Loop{
|
|
settings: settings,
|
|
}
|
|
}
|
|
|
|
func (l *Loop) String() string {
|
|
return "SOCKS5 server loop"
|
|
}
|
|
|
|
func (l *Loop) Start(_ context.Context) (runError <-chan error, err error) {
|
|
l.mutex.Lock()
|
|
defer l.mutex.Unlock()
|
|
|
|
var runCtx context.Context
|
|
runCtx, l.runCancel = context.WithCancel(context.Background())
|
|
|
|
runDone := make(chan error)
|
|
l.runDone = runDone
|
|
|
|
go run(runCtx, runDone, l.settings)
|
|
|
|
return nil, nil //nolint:nilnil
|
|
}
|
|
|
|
func run(ctx context.Context, done chan<- error, settings Settings) {
|
|
defer close(done)
|
|
logger := settings.Logger
|
|
|
|
for ctx.Err() == nil {
|
|
var server goservices.Service
|
|
if settings.Enabled {
|
|
server = newServer(settings)
|
|
} else {
|
|
server = new(noopService)
|
|
}
|
|
|
|
errorCh, err := server.Start(ctx)
|
|
if err != nil {
|
|
logger.Warnf("failed starting SOCKS5 server: %s", err)
|
|
waitBeforeRetry(ctx)
|
|
continue
|
|
}
|
|
|
|
select {
|
|
case <-ctx.Done():
|
|
done <- server.Stop()
|
|
return
|
|
case err := <-errorCh:
|
|
if ctx.Err() != nil {
|
|
return
|
|
}
|
|
logger.Warnf("SOCKS5 server crashed: %s", err)
|
|
waitBeforeRetry(ctx)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (l *Loop) Stop() (err error) {
|
|
l.mutex.Lock()
|
|
defer l.mutex.Unlock()
|
|
|
|
l.runCancel()
|
|
return <-l.runDone
|
|
}
|
|
|
|
func waitBeforeRetry(ctx context.Context) {
|
|
const retryDelay = 10 * time.Second
|
|
timer := time.NewTimer(retryDelay)
|
|
select {
|
|
case <-timer.C:
|
|
case <-ctx.Done():
|
|
}
|
|
}
|
|
|
|
type noopService struct{}
|
|
|
|
func (s noopService) Start(_ context.Context) (runErr <-chan error, err error) {
|
|
return nil, nil //nolint:nilnil
|
|
}
|
|
|
|
func (s noopService) Stop() error {
|
|
return nil
|
|
}
|
|
|
|
func (s noopService) String() string {
|
|
return "noop service"
|
|
}
|