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

     1  /*
     2   * Copyright (C) 2022 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 connection
    19  
    20  import (
    21  	"context"
    22  	"sync"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/rs/zerolog/log"
    26  
    27  	"github.com/mysteriumnetwork/node/core/connection/connectionstate"
    28  	"github.com/mysteriumnetwork/node/identity"
    29  )
    30  
    31  type multiConnectionManager struct {
    32  	mu  sync.RWMutex
    33  	cms map[int]Manager
    34  
    35  	newConnectionManager func() Manager
    36  }
    37  
    38  // NewMultiConnectionManager create a wrapper around connection manager to support multiple connections.
    39  func NewMultiConnectionManager(newConnectionManager func() Manager) *multiConnectionManager {
    40  	return &multiConnectionManager{
    41  		cms: make(map[int]Manager),
    42  
    43  		newConnectionManager: newConnectionManager,
    44  	}
    45  }
    46  
    47  // Connect creates new connection from given consumer to provider, reports error if connection already exists.
    48  func (mcm *multiConnectionManager) Connect(consumerID identity.Identity, hermesID common.Address, proposalLookup ProposalLookup, params ConnectParams) error {
    49  	mcm.mu.Lock()
    50  
    51  	m, ok := mcm.cms[params.ProxyPort]
    52  	if !ok {
    53  		m = mcm.newConnectionManager()
    54  		mcm.cms[params.ProxyPort] = m
    55  	}
    56  	mcm.mu.Unlock()
    57  
    58  	return m.Connect(consumerID, hermesID, proposalLookup, params)
    59  }
    60  
    61  // Status queries current status of connection.
    62  func (mcm *multiConnectionManager) Status(id int) connectionstate.Status {
    63  	mcm.mu.RLock()
    64  	defer mcm.mu.RUnlock()
    65  
    66  	if m, ok := mcm.cms[id]; ok {
    67  		return m.Status()
    68  	}
    69  
    70  	return connectionstate.Status{
    71  		State: connectionstate.NotConnected,
    72  	}
    73  }
    74  
    75  // Stats provides connection statistics information.
    76  func (mcm *multiConnectionManager) Stats(id int) connectionstate.Statistics {
    77  	mcm.mu.RLock()
    78  	defer mcm.mu.RUnlock()
    79  
    80  	if m, ok := mcm.cms[id]; ok {
    81  		return m.Stats()
    82  	}
    83  
    84  	return connectionstate.Statistics{}
    85  }
    86  
    87  // Disconnect closes established connection, reports error if no connection.
    88  func (mcm *multiConnectionManager) Disconnect(id int) error {
    89  	mcm.mu.RLock()
    90  	m, ok := mcm.cms[id]
    91  	mcm.mu.RUnlock()
    92  
    93  	if ok {
    94  		err := m.Disconnect()
    95  		return err
    96  	}
    97  
    98  	if id < 0 {
    99  		mcm.mu.RLock()
   100  		defer mcm.mu.RUnlock()
   101  
   102  		for _, m := range mcm.cms {
   103  			if err := m.Disconnect(); err != nil {
   104  				log.Error().Err(err).Msg("Failed to disconnect active connection")
   105  			}
   106  		}
   107  	}
   108  
   109  	return nil
   110  }
   111  
   112  // CheckChannel checks if current session channel is alive, returns error on failed keep-alive ping.
   113  func (mcm *multiConnectionManager) CheckChannel(context.Context) error { return nil }
   114  
   115  // Reconnect reconnects current session.
   116  func (mcm *multiConnectionManager) Reconnect(id int) {
   117  	mcm.mu.RLock()
   118  	defer mcm.mu.RUnlock()
   119  
   120  	if m, ok := mcm.cms[id]; ok {
   121  		m.Reconnect()
   122  	}
   123  }