Public IP loop, fixes #186

- Uses common http client with 15 seconds timeout
- Repeats on fail after 5 seconds sleep time
This commit is contained in:
Quentin McGaw
2020-07-08 22:33:28 +00:00
parent 7450ffce2b
commit 53b7fafc49
2 changed files with 81 additions and 20 deletions

View File

@@ -208,6 +208,7 @@ func _main(background context.Context, args []string) int {
restartOpenvpn := make(chan struct{})
restartUnbound := make(chan struct{})
restartPublicIP := make(chan struct{})
openvpnDone := make(chan struct{})
unboundDone := make(chan struct{})
serverDone := make(chan struct{})
@@ -220,6 +221,9 @@ func _main(background context.Context, args []string) int {
// wait for restartUnbound
go unboundLooper.Run(ctx, restartUnbound, unboundDone)
publicIPLooper := publicip.NewLooper(client, logger, fileManager, allSettings.System.IPStatusFilepath, uid, gid)
go publicIPLooper.Run(ctx, restartPublicIP)
go func() {
first := true
var restartTickerContext context.Context
@@ -237,7 +241,7 @@ func _main(background context.Context, args []string) int {
restartTickerCancel()
restartTickerContext, restartTickerCancel = context.WithCancel(ctx)
go unboundLooper.RunRestartTicker(restartTickerContext, restartUnbound)
onConnected(allSettings, logger, fileManager, routingConf, defaultInterface, providerConf)
onConnected(allSettings, logger, routingConf, defaultInterface, providerConf, restartPublicIP)
}
}
}()
@@ -355,10 +359,10 @@ func trimEventualProgramPrefix(s string) string {
}
func onConnected(allSettings settings.Settings,
logger logging.Logger, fileManager files.FileManager,
routingConf routing.Routing, defaultInterface string,
providerConf provider.Provider,
logger logging.Logger, routingConf routing.Routing, defaultInterface string,
providerConf provider.Provider, restartPublicIP chan<- struct{},
) {
restartPublicIP <- struct{}{}
uid, gid := allSettings.System.UID, allSettings.System.GID
if allSettings.OpenVPN.Provider.PortForwarding.Enabled {
time.AfterFunc(5*time.Second, func() {
@@ -372,22 +376,6 @@ func onConnected(allSettings settings.Settings,
} else {
logger.Info("Gateway VPN IP address: %s", vpnGatewayIP)
}
time.AfterFunc(10*time.Second, func() { // wait for Unbound to start - TODO use signal channel
publicIP, err := publicip.NewIPGetter(network.NewClient(3 * time.Second)).Get()
if err != nil {
logger.Error(err)
} else {
logger.Info("Public IP address is %s", publicIP)
err = fileManager.WriteLinesToFile(
string(allSettings.System.IPStatusFilepath),
[]string{publicIP.String()},
files.Ownership(uid, gid),
files.Permissions(0400))
if err != nil {
logger.Error(err)
}
}
})
}
func setupPortForwarding(logger logging.Logger, providerConf provider.Provider, filepath models.Filepath, uid, gid int) {

73
internal/publicip/loop.go Normal file
View File

@@ -0,0 +1,73 @@
package publicip
import (
"context"
"time"
"github.com/qdm12/golibs/files"
"github.com/qdm12/golibs/logging"
"github.com/qdm12/golibs/network"
"github.com/qdm12/private-internet-access-docker/internal/models"
)
type Looper interface {
Run(ctx context.Context, restart <-chan struct{})
}
type looper struct {
getter IPGetter
logger logging.Logger
fileManager files.FileManager
ipStatusFilepath models.Filepath
uid int
gid int
}
func NewLooper(client network.Client, logger logging.Logger, fileManager files.FileManager,
ipStatusFilepath models.Filepath, uid, gid int) Looper {
return &looper{
getter: NewIPGetter(client),
logger: logger.WithPrefix("ip getter: "),
fileManager: fileManager,
ipStatusFilepath: ipStatusFilepath,
uid: uid,
gid: gid,
}
}
func (l *looper) logAndWait(err error) {
l.logger.Error(err)
l.logger.Info("retrying in 5 seconds")
time.Sleep(5 * time.Second)
}
func (l *looper) Run(ctx context.Context, restart <-chan struct{}) {
select {
case <-restart:
case <-ctx.Done():
return
}
for {
ip, err := l.getter.Get()
if err != nil {
l.logAndWait(err)
continue
}
l.logger.Info("Public IP address is %s", ip)
err = l.fileManager.WriteLinesToFile(
string(l.ipStatusFilepath),
[]string{ip.String()},
files.Ownership(l.uid, l.gid),
files.Permissions(0600))
if err != nil {
l.logAndWait(err)
continue
}
select {
case <-restart: // triggered restart
case <-ctx.Done():
l.logger.Warn("context canceled: exiting loop")
return
}
}
}