mirror of
				https://source.quilibrium.com/quilibrium/ceremonyclient.git
				synced 2025-11-04 00:57:26 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			97 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			97 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package relaysvc
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"sync"
 | 
						|
 | 
						|
	"github.com/libp2p/go-libp2p/core/event"
 | 
						|
	"github.com/libp2p/go-libp2p/core/host"
 | 
						|
	"github.com/libp2p/go-libp2p/core/network"
 | 
						|
	"github.com/libp2p/go-libp2p/p2p/host/eventbus"
 | 
						|
	relayv2 "github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/relay"
 | 
						|
)
 | 
						|
 | 
						|
type RelayManager struct {
 | 
						|
	host host.Host
 | 
						|
 | 
						|
	mutex sync.Mutex
 | 
						|
	relay *relayv2.Relay
 | 
						|
	opts  []relayv2.Option
 | 
						|
 | 
						|
	refCount  sync.WaitGroup
 | 
						|
	ctxCancel context.CancelFunc
 | 
						|
}
 | 
						|
 | 
						|
func NewRelayManager(host host.Host, opts ...relayv2.Option) *RelayManager {
 | 
						|
	ctx, cancel := context.WithCancel(context.Background())
 | 
						|
	m := &RelayManager{
 | 
						|
		host:      host,
 | 
						|
		opts:      opts,
 | 
						|
		ctxCancel: cancel,
 | 
						|
	}
 | 
						|
	m.refCount.Add(1)
 | 
						|
	go m.background(ctx)
 | 
						|
	return m
 | 
						|
}
 | 
						|
 | 
						|
func (m *RelayManager) background(ctx context.Context) {
 | 
						|
	defer m.refCount.Done()
 | 
						|
	defer func() {
 | 
						|
		m.mutex.Lock()
 | 
						|
		if m.relay != nil {
 | 
						|
			m.relay.Close()
 | 
						|
		}
 | 
						|
		m.mutex.Unlock()
 | 
						|
	}()
 | 
						|
 | 
						|
	subReachability, _ := m.host.EventBus().Subscribe(new(event.EvtLocalReachabilityChanged), eventbus.Name("relaysvc"))
 | 
						|
	defer subReachability.Close()
 | 
						|
 | 
						|
	for {
 | 
						|
		select {
 | 
						|
		case <-ctx.Done():
 | 
						|
			return
 | 
						|
		case ev, ok := <-subReachability.Out():
 | 
						|
			if !ok {
 | 
						|
				return
 | 
						|
			}
 | 
						|
			if err := m.reachabilityChanged(ev.(event.EvtLocalReachabilityChanged).Reachability); err != nil {
 | 
						|
				return
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (m *RelayManager) reachabilityChanged(r network.Reachability) error {
 | 
						|
	switch r {
 | 
						|
	case network.ReachabilityPublic:
 | 
						|
		m.mutex.Lock()
 | 
						|
		defer m.mutex.Unlock()
 | 
						|
		// This could happen if two consecutive EvtLocalReachabilityChanged report the same reachability.
 | 
						|
		// This shouldn't happen, but it's safer to double-check.
 | 
						|
		if m.relay != nil {
 | 
						|
			return nil
 | 
						|
		}
 | 
						|
		relay, err := relayv2.New(m.host, m.opts...)
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		m.relay = relay
 | 
						|
	default:
 | 
						|
		m.mutex.Lock()
 | 
						|
		defer m.mutex.Unlock()
 | 
						|
		if m.relay != nil {
 | 
						|
			err := m.relay.Close()
 | 
						|
			m.relay = nil
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (m *RelayManager) Close() error {
 | 
						|
	m.ctxCancel()
 | 
						|
	m.refCount.Wait()
 | 
						|
	return nil
 | 
						|
}
 |