Skip to content

Commit

Permalink
Merge pull request #470 from Darkren/fix/vpn-client-remote-startup
Browse files Browse the repository at this point in the history
Fix VPN client remote startup
  • Loading branch information
jdknives committed Aug 13, 2020
2 parents 20b10fb + 2ee663d commit fecd744
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 16 deletions.
22 changes: 19 additions & 3 deletions internal/vpn/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func NewClient(cfg ClientConfig, l logrus.FieldLogger, conn net.Conn) (*Client,
cfg: cfg,
log: l,
conn: conn,
directIPs: directIPs,
directIPs: filterOutEqualIPs(directIPs),
defaultGateway: defaultGateway,
closeC: make(chan struct{}),
}, nil
Expand Down Expand Up @@ -199,9 +199,9 @@ func (c *Client) routeTrafficDirectly(tunGateway net.IP) {
func (c *Client) setupDirectRoutes() error {
for _, ip := range c.directIPs {
if !ip.IsLoopback() {
c.log.Infof("Adding direct route to %s", ip.String())
c.log.Infof("Adding direct route to %s, via %s", ip.String(), c.defaultGateway.String())
if err := AddRoute(ip.String()+directRouteNetmaskCIDR, c.defaultGateway.String()); err != nil {
return fmt.Errorf("error adding direct route to %s", ip.String())
return fmt.Errorf("error adding direct route to %s: %w", ip.String(), err)
}
}
}
Expand Down Expand Up @@ -332,3 +332,19 @@ func ipFromEnv(key string) (net.IP, error) {

return ip, nil
}

func filterOutEqualIPs(ips []net.IP) []net.IP {
ipsSet := make(map[string]struct{})
var filteredIPs []net.IP
for _, ip := range ips {
ipStr := ip.String()

if _, ok := ipsSet[ipStr]; !ok {
filteredIPs = append(filteredIPs, ip)
ipsSet[ip.String()] = struct{}{}
}
}

return filteredIPs

}
62 changes: 50 additions & 12 deletions pkg/app/appserver/proc.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,14 @@ type Proc struct {
conn net.Conn // connection to proc - introduced AFTER proc is started
connCh chan struct{} // push here when conn is received - protected by 'connOnce'
connOnce sync.Once // ensures we only push to 'connCh' once

m ProcManager
appName string
}

// NewProc constructs `Proc`.
func NewProc(mLog *logging.MasterLogger, conf appcommon.ProcConfig, disc appdisc.Updater) *Proc {
func NewProc(mLog *logging.MasterLogger, conf appcommon.ProcConfig, disc appdisc.Updater, m ProcManager,
appName string) *Proc {
if mLog == nil {
mLog = logging.NewMasterLogger()
}
Expand All @@ -60,12 +64,14 @@ func NewProc(mLog *logging.MasterLogger, conf appcommon.ProcConfig, disc appdisc
cmd.Stderr = appLog.WithField("_module", moduleName).WithField("func", "(STDERR)").Writer()

return &Proc{
disc: disc,
conf: conf,
log: mLog.PackageLogger(moduleName),
logDB: appLogDB,
cmd: cmd,
connCh: make(chan struct{}, 1),
disc: disc,
conf: conf,
log: mLog.PackageLogger(moduleName),
logDB: appLogDB,
cmd: cmd,
connCh: make(chan struct{}, 1),
m: m,
appName: appName,
}
}

Expand Down Expand Up @@ -99,10 +105,6 @@ func (p *Proc) InjectConn(conn net.Conn) bool {
}

func (p *Proc) awaitConn() bool {
if _, ok := <-p.connCh; !ok {
return false
}

rpcS := rpc.NewServer()
if err := rpcS.RegisterName(p.conf.ProcKey.String(), p.rpcGW); err != nil {
panic(err)
Expand Down Expand Up @@ -149,6 +151,42 @@ func (p *Proc) Start() error {
}

go func() {
waitErrCh := make(chan error)
go func() {
waitErrCh <- p.cmd.Wait()
close(waitErrCh)
}()

select {
case _, ok := <-p.connCh:
if !ok {
// in this case app got stopped from the outer code before initializing the connection,
// just kill the process and exit.
_ = p.cmd.Process.Kill() //nolint:errcheck
p.waitMx.Unlock()

return
}
case waitErr := <-waitErrCh:
// in this case app process finished before initializing the connection. Happens if an
// error occurred during app startup.
p.waitErr = waitErr
p.waitMx.Unlock()

// channel won't get closed outside, close it now.
p.connOnce.Do(func() { close(p.connCh) })

// here will definitely be an error notifying that the process
// is already stopped. We do this to remove proc from the manager,
// therefore giving the correct app status to hypervisor.
_ = p.m.Stop(p.appName) //nolint:errcheck

return
}

// here, the connection is established, so we're not blocked by awaiting it anymore,
// execution may be continued as usual.

if ok := p.awaitConn(); !ok {
_ = p.cmd.Process.Kill() //nolint:errcheck
p.waitMx.Unlock()
Expand All @@ -160,7 +198,7 @@ func (p *Proc) Start() error {
defer p.disc.Stop()

// Wait for proc to exit.
p.waitErr = p.cmd.Wait()
p.waitErr = <-waitErrCh

// Close proc conn and associated listeners and connections.
if err := p.conn.Close(); err != nil && !strings.Contains(err.Error(), "use of closed network connection") {
Expand Down
2 changes: 1 addition & 1 deletion pkg/app/appserver/proc_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ func (m *procManager) Start(conf appcommon.ProcConfig) (appcommon.ProcID, error)
Debug("No app discovery associated with app.")
}

proc := NewProc(m.mLog, conf, disc)
proc := NewProc(m.mLog, conf, disc, m, conf.AppName)
m.procs[conf.AppName] = proc
m.procsByKey[conf.ProcKey] = proc

Expand Down

0 comments on commit fecd744

Please sign in to comment.