Files
gluetun/internal/portforward/service/service.go
T
2026-04-18 02:36:06 +02:00

85 lines
1.7 KiB
Go

package service
import (
"context"
"fmt"
"net/http"
"slices"
"sync"
)
type Service struct {
// State
portMutex sync.RWMutex
ports []uint16
// Fixed parameters
settings Settings
puid int
pgid int
// Fixed injected objects
routing Routing
client *http.Client
portAllower PortAllower
logger Logger
cmder Cmder
// Internal channels and locks
startStopMutex sync.Mutex
keepPortCancel context.CancelFunc
keepPortDoneCh <-chan struct{}
}
func New(settings Settings, routing Routing, client *http.Client,
portAllower PortAllower, logger Logger, cmder Cmder, puid, pgid int,
) *Service {
return &Service{
// Fixed parameters
settings: settings,
puid: puid,
pgid: pgid,
// Fixed injected objects
routing: routing,
client: client,
portAllower: portAllower,
logger: logger,
cmder: cmder,
}
}
func (s *Service) GetPortsForwarded() (ports []uint16) {
s.portMutex.RLock()
defer s.portMutex.RUnlock()
ports = make([]uint16, len(s.ports))
copy(ports, s.ports)
return ports
}
func (s *Service) SetPortsForwarded(ctx context.Context, ports []uint16) (err error) {
s.startStopMutex.Lock()
defer s.startStopMutex.Unlock()
s.portMutex.Lock()
defer s.portMutex.Unlock()
slices.Sort(ports)
if slices.Equal(s.ports, ports) {
return nil
}
err = s.cleanup()
if err != nil {
return fmt.Errorf("cleaning up: %w", err)
}
internalToExternalPorts := make(map[uint16]uint16, len(ports))
for _, port := range ports {
internalToExternalPorts[port] = port
}
err = s.onNewPorts(ctx, internalToExternalPorts)
if err != nil {
return fmt.Errorf("handling new ports: %w", err)
}
s.logger.Info("updated: " + portsToString(s.ports))
return nil
}