github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/sleep/sleep.go (about)

     1  /*
     2   * Copyright (C) 2020 The "MysteriumNetwork/node" Authors.
     3   *
     4   * This program is free software: you can redistribute it and/or modify
     5   * it under the terms of the GNU General Public License as published by
     6   * the Free Software Foundation, either version 3 of the License, or
     7   * (at your option) any later version.
     8   *
     9   * This program is distributed in the hope that it will be useful,
    10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12   * GNU General Public License for more details.
    13   *
    14   * You should have received a copy of the GNU General Public License
    15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16   */
    17  
    18  package sleep
    19  
    20  import (
    21  	"sync"
    22  	"time"
    23  
    24  	"github.com/rs/zerolog/log"
    25  	"golang.org/x/net/context"
    26  
    27  	"github.com/mysteriumnetwork/node/core/connection/connectionstate"
    28  	"github.com/mysteriumnetwork/node/eventbus"
    29  )
    30  
    31  // Event represents sleep event triggered by underlying OS
    32  type Event int
    33  
    34  const (
    35  	// AppTopicSleepNotification represents sleep management Event notification
    36  	AppTopicSleepNotification = "sleep_notification"
    37  
    38  	// EventWakeup event sent to node after OS wakes up from sleep
    39  	EventWakeup Event = iota
    40  	// EventSleep event sent to node after OS goes to sleep
    41  	EventSleep
    42  )
    43  
    44  var eventChannel chan Event
    45  
    46  // Notifier represents sleep event notifier structure
    47  type Notifier struct {
    48  	eventBus          eventbus.EventBus
    49  	stop              chan struct{}
    50  	stopOnce          sync.Once
    51  	connectionManager connectionManager
    52  }
    53  
    54  type connectionManager interface {
    55  	// Status queries current status of connection
    56  	Status(int) connectionstate.Status
    57  	// CheckChannel checks if current session channel is alive, returns error on failed keep-alive ping
    58  	CheckChannel(context.Context) error
    59  	// Reconnect reconnects current session
    60  	Reconnect(int)
    61  }
    62  
    63  // NewNotifier create sleep events notifier
    64  func NewNotifier(manager connectionManager, eventbus eventbus.EventBus) *Notifier {
    65  	eventChannel = make(chan Event)
    66  	return &Notifier{
    67  		connectionManager: manager,
    68  		eventBus:          eventbus,
    69  		stop:              make(chan struct{}),
    70  	}
    71  }
    72  
    73  func (n *Notifier) handleSleepEvent(e Event) {
    74  	switch e {
    75  	case EventSleep:
    76  		log.Info().Msg("Got sleep notification during live vpn session")
    77  	case EventWakeup:
    78  		log.Info().Msg("Got wake-up from sleep notification - checking if need to reconnect")
    79  		if n.connectionManager.Status(0).State != connectionstate.Connected {
    80  			return
    81  		}
    82  		ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond)
    83  		defer cancel()
    84  		if err := n.connectionManager.CheckChannel(ctx); err != nil {
    85  			log.Info().Msgf("Channel dead - reconnecting: %s", err)
    86  			n.connectionManager.Reconnect(0)
    87  		} else {
    88  			log.Info().Msg("Channel still alive - no need to reconnect")
    89  		}
    90  	}
    91  }
    92  
    93  // Subscribe subscribes to sleep notifications
    94  func (n *Notifier) Subscribe() {
    95  	n.eventBus.SubscribeAsync(AppTopicSleepNotification, n.handleSleepEvent)
    96  }