Skip to content

Commit

Permalink
Improve HeartBeat events
Browse files Browse the repository at this point in the history
* HeartBeat events are now sent once meshnet setting updates
* `is_on_vpn` value is always updated after connect and disconnect

Signed-off-by: Savolro <[email protected]>
  • Loading branch information
Savolro committed Oct 17, 2024
1 parent 770afdc commit dc68670
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 22 deletions.
4 changes: 3 additions & 1 deletion cmd/daemon/events_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
package main

import (
"time"

"github.com/NordSecurity/nordvpn-linux/config"
"github.com/NordSecurity/nordvpn-linux/core"
"github.com/NordSecurity/nordvpn-linux/events"
Expand Down Expand Up @@ -34,7 +36,7 @@ func (*dummyAnalytics) NotifyMFA(bool) error { return n
func (*dummyAnalytics) NotifyAccountCheck(any) error { return nil }
func (*dummyAnalytics) NotifyRequestAPI(events.DataRequestAPI) error { return nil }
func (*dummyAnalytics) NotifyUiItemsClick(events.UiItemsAction) error { return nil }
func (*dummyAnalytics) NotifyHeartBeat(int) error { return nil }
func (*dummyAnalytics) NotifyHeartBeat(time.Duration) error { return nil }
func (*dummyAnalytics) NotifyDeviceLocation(core.Insights) error { return nil }
func (*dummyAnalytics) NotifyLANDiscovery(bool) error { return nil }
func (*dummyAnalytics) NotifyVirtualLocation(bool) error { return nil }
Expand Down
8 changes: 7 additions & 1 deletion cmd/daemon/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"path/filepath"
"runtime"
"strconv"
"time"

"golang.org/x/net/netutil"

Expand Down Expand Up @@ -149,6 +150,7 @@ func main() {
debugSubject := &subs.Subject[string]{}
infoSubject := &subs.Subject[string]{}
errSubject := &subs.Subject[error]{}
heartBeatSubject := &subs.Subject[time.Duration]{}
httpCallsSubject := &subs.Subject[events.DataRequestAPI]{}

loggerSubscriber := logger.Subscriber{}
Expand Down Expand Up @@ -290,6 +292,10 @@ func main() {
daemonEvents.Service.Connect.Subscribe(loggerSubscriber.NotifyConnect)
daemonEvents.Settings.Publish(cfg)

// Subscribing after initial settings publishing ensures that heartbeat is not sent with
// the first `NotifyMeshnet` call but will be sent on the first heartbeat job.
heartBeatSubject.Subscribe(analytics.NotifyHeartBeat)

if fsystem.NewInstallation {
daemonEvents.Service.UiItemsClick.Publish(events.UiItemsAction{ItemName: "first_open", ItemType: "button", ItemValue: "first_open", FormReference: "daemon"})
}
Expand Down Expand Up @@ -556,7 +562,7 @@ func main() {
log.Println(internal.WarningPrefix, err)
}
}()
rpc.StartJobs(statePublisher)
rpc.StartJobs(statePublisher, heartBeatSubject)
meshService.StartJobs()
rpc.StartKillSwitch()
if internal.IsSystemd() {
Expand Down
4 changes: 0 additions & 4 deletions daemon/events/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ func NewEvents(
Disconnect: disconnect,
AccountCheck: accountCheck,
UiItemsClick: uiItemsClick,
HeartBeat: heartBeat,
DeviceLocation: deviceLocation,
},
User: &LoginEvents{
Expand Down Expand Up @@ -187,7 +186,6 @@ type ServicePublisher interface {
NotifyDisconnect(events.DataDisconnect) error
NotifyAccountCheck(any) error
NotifyUiItemsClick(events.UiItemsAction) error
NotifyHeartBeat(int) error
NotifyDeviceLocation(core.Insights) error
}

Expand All @@ -196,7 +194,6 @@ type ServiceEvents struct {
Disconnect events.PublishSubcriber[events.DataDisconnect]
AccountCheck events.PublishSubcriber[any]
UiItemsClick events.PublishSubcriber[events.UiItemsAction]
HeartBeat events.PublishSubcriber[int]
DeviceLocation events.PublishSubcriber[core.Insights]
}

Expand All @@ -205,7 +202,6 @@ func (s *ServiceEvents) Subscribe(to ServicePublisher) {
s.Disconnect.Subscribe(to.NotifyDisconnect)
s.AccountCheck.Subscribe(to.NotifyAccountCheck)
s.UiItemsClick.Subscribe(to.NotifyUiItemsClick)
s.HeartBeat.Subscribe(to.NotifyHeartBeat)
s.DeviceLocation.Subscribe(to.NotifyDeviceLocation)
}

Expand Down
1 change: 0 additions & 1 deletion daemon/events/events_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ func (mockDaemonSubscriber) NotifyIpv6(bool) error { ret
func (mockDaemonSubscriber) NotifyDefaults(any) error { return nil }
func (mockDaemonSubscriber) NotifyMeshnet(bool) error { return nil }
func (mockDaemonSubscriber) NotifyUiItemsClick(events.UiItemsAction) error { return nil }
func (mockDaemonSubscriber) NotifyHeartBeat(int) error { return nil }
func (mockDaemonSubscriber) NotifyDeviceLocation(core.Insights) error { return nil }
func (mockDaemonSubscriber) NotifyLANDiscovery(bool) error { return nil }
func (mockDaemonSubscriber) NotifyVirtualLocation(bool) error { return nil }
Expand Down
10 changes: 6 additions & 4 deletions daemon/job_heartbeat.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
package daemon

import (
"github.com/NordSecurity/nordvpn-linux/daemon/events"
"time"

"github.com/NordSecurity/nordvpn-linux/events"
)

// JobHeartBeat sends heart beats.
func JobHeartBeat(
timePeriod int,
events *events.Events,
publisher events.Publisher[time.Duration],
period time.Duration,
) func() {
return func() {
events.Service.HeartBeat.Publish(timePeriod)
publisher.Publish(period)
}
}
11 changes: 9 additions & 2 deletions daemon/jobs.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,14 @@ import (
"google.golang.org/grpc/metadata"
)

func (r *RPC) StartJobs(statePublisher *state.StatePublisher) {
const (
heartBeatPeriod = time.Hour * 24
)

func (r *RPC) StartJobs(
statePublisher *state.StatePublisher,
heartBeatPublisher events.Publisher[time.Duration],
) {
// order of the jobs below matters
// servers job requires geo info and configs data to create server list
// TODO what if configs file is deleted just before servers job or disk is full?
Expand Down Expand Up @@ -51,7 +58,7 @@ func (r *RPC) StartJobs(statePublisher *state.StatePublisher) {
log.Println(internal.WarningPrefix, "job version schedule error:", err)
}

if _, err := r.scheduler.NewJob(gocron.DurationJob(24*time.Hour), gocron.NewTask(JobHeartBeat(1*24*60 /*minutes*/, r.events)), gocron.WithName("job heart beat")); err != nil {
if _, err := r.scheduler.NewJob(gocron.DurationJob(heartBeatPeriod), gocron.NewTask(JobHeartBeat(heartBeatPublisher, heartBeatPeriod), gocron.WithName("job heart beat"))); err != nil {
log.Println(internal.WarningPrefix, "job heart beat schedule error:", err)
}
if _, err := r.scheduler.NewJob(gocron.DurationJob(7*24*time.Hour), gocron.NewTask(func() {
Expand Down
33 changes: 24 additions & 9 deletions events/moose/moose.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,8 +346,8 @@ func (s *Subscriber) NotifyUiItemsClick(data events.UiItemsAction) error {
))
}

func (s *Subscriber) NotifyHeartBeat(timePeriodMinutes int) error {
return s.response(moose.NordvpnappSendServiceQualityStatusHeartbeat(int32(timePeriodMinutes)))
func (s *Subscriber) NotifyHeartBeat(period time.Duration) error {
return s.response(moose.NordvpnappSendServiceQualityStatusHeartbeat(int32(period.Minutes())))
}

func (s *Subscriber) NotifyDeviceLocation(insights core.Insights) error {
Expand All @@ -369,7 +369,11 @@ func (s *Subscriber) NotifyDeviceLocation(insights core.Insights) error {
func (s *Subscriber) NotifyNotify(bool) error { return nil }

func (s *Subscriber) NotifyMeshnet(data bool) error {
return s.response(moose.NordvpnappSetContextApplicationNordvpnappConfigUserPreferencesMeshnetEnabledValue(data))
if err := s.response(moose.NordvpnappSetContextApplicationNordvpnappConfigUserPreferencesMeshnetEnabledValue(data)); err != nil {
return err
}
// 0 duration indicates that this is not a periodic heart beat
return s.NotifyHeartBeat(time.Duration(0))
}

func (s *Subscriber) NotifyObfuscate(data bool) error {
Expand Down Expand Up @@ -499,7 +503,7 @@ func (s *Subscriber) NotifyConnect(data events.DataConnect) error {
default:
rule = moose.NordvpnappServerSelectionRuleRecommended
}
return s.response(moose.NordvpnappSendServiceQualityServersConnect(
if err := s.response(moose.NordvpnappSendServiceQualityServersConnect(
int32(data.DurationMs),
eventStatus,
moose.NordvpnappEventTriggerUser,
Expand All @@ -518,7 +522,13 @@ func (s *Subscriber) NotifyConnect(data events.DataConnect) error {
int32(-1),
"",
int32(-1),
))
)); err != nil {
return err
}
if data.EventStatus == events.StatusSuccess {
return s.response(moose.NordvpnappSetContextApplicationNordvpnappConfigCurrentStateIsOnVpnValue(true))
}
return nil
}
}

Expand All @@ -539,13 +549,15 @@ func (s *Subscriber) NotifyDisconnect(data events.DataDisconnect) error {
}

if s.connectionToMeshnetPeer {
return s.response(moose.NordvpnappSendServiceQualityServersDisconnectFromMeshnetDevice(
if err := s.response(moose.NordvpnappSendServiceQualityServersDisconnectFromMeshnetDevice(
int32(-1),
eventStatus,
moose.NordvpnappEventTriggerUser,
connectionTime, // seconds
int32(-1),
))
)); err != nil {
return err
}
} else {
var technology moose.NordvpnappVpnConnectionTechnology
switch data.Technology {
Expand Down Expand Up @@ -591,7 +603,7 @@ func (s *Subscriber) NotifyDisconnect(data events.DataDisconnect) error {
threatProtection = moose.NordvpnappOptBoolFalse
}

return s.response(moose.NordvpnappSendServiceQualityServersDisconnect(
if err := s.response(moose.NordvpnappSendServiceQualityServersDisconnect(
int32(-1),
eventStatus,
moose.NordvpnappEventTriggerUser,
Expand All @@ -610,8 +622,11 @@ func (s *Subscriber) NotifyDisconnect(data events.DataDisconnect) error {
connectionTime, // seconds
"",
int32(-1),
))
)); err != nil {
return err
}
}
return s.response(moose.NordvpnappSetContextApplicationNordvpnappConfigCurrentStateIsOnVpnValue(false))
}

func (s *Subscriber) NotifyRequestAPI(data events.DataRequestAPI) error {
Expand Down

0 comments on commit dc68670

Please sign in to comment.