mirror of
				https://source.quilibrium.com/quilibrium/ceremonyclient.git
				synced 2025-11-04 08:37:29 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			164 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			164 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package client
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"net"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/libp2p/go-libp2p/core/network"
 | 
						|
	"github.com/libp2p/go-libp2p/core/peer"
 | 
						|
	tpt "github.com/libp2p/go-libp2p/core/transport"
 | 
						|
 | 
						|
	ma "github.com/multiformats/go-multiaddr"
 | 
						|
	manet "github.com/multiformats/go-multiaddr/net"
 | 
						|
)
 | 
						|
 | 
						|
// HopTagWeight is the connection manager weight for connections carrying relay hop streams
 | 
						|
var HopTagWeight = 5
 | 
						|
 | 
						|
type statLimitDuration struct{}
 | 
						|
type statLimitData struct{}
 | 
						|
 | 
						|
var (
 | 
						|
	StatLimitDuration = statLimitDuration{}
 | 
						|
	StatLimitData     = statLimitData{}
 | 
						|
)
 | 
						|
 | 
						|
type Conn struct {
 | 
						|
	stream network.Stream
 | 
						|
	remote peer.AddrInfo
 | 
						|
	stat   network.ConnStats
 | 
						|
 | 
						|
	client *Client
 | 
						|
}
 | 
						|
 | 
						|
type NetAddr struct {
 | 
						|
	Relay  string
 | 
						|
	Remote string
 | 
						|
}
 | 
						|
 | 
						|
var _ net.Addr = (*NetAddr)(nil)
 | 
						|
 | 
						|
func (n *NetAddr) Network() string {
 | 
						|
	return "libp2p-circuit-relay"
 | 
						|
}
 | 
						|
 | 
						|
func (n *NetAddr) String() string {
 | 
						|
	return fmt.Sprintf("relay[%s-%s]", n.Remote, n.Relay)
 | 
						|
}
 | 
						|
 | 
						|
// Conn interface
 | 
						|
var _ manet.Conn = (*Conn)(nil)
 | 
						|
 | 
						|
func (c *Conn) Close() error {
 | 
						|
	c.untagHop()
 | 
						|
	return c.stream.Reset()
 | 
						|
}
 | 
						|
 | 
						|
func (c *Conn) Read(buf []byte) (int, error) {
 | 
						|
	return c.stream.Read(buf)
 | 
						|
}
 | 
						|
 | 
						|
func (c *Conn) Write(buf []byte) (int, error) {
 | 
						|
	return c.stream.Write(buf)
 | 
						|
}
 | 
						|
 | 
						|
func (c *Conn) SetDeadline(t time.Time) error {
 | 
						|
	return c.stream.SetDeadline(t)
 | 
						|
}
 | 
						|
 | 
						|
func (c *Conn) SetReadDeadline(t time.Time) error {
 | 
						|
	return c.stream.SetReadDeadline(t)
 | 
						|
}
 | 
						|
 | 
						|
func (c *Conn) SetWriteDeadline(t time.Time) error {
 | 
						|
	return c.stream.SetWriteDeadline(t)
 | 
						|
}
 | 
						|
 | 
						|
// TODO: is it okay to cast c.Conn().RemotePeer() into a multiaddr? might be "user input"
 | 
						|
func (c *Conn) RemoteMultiaddr() ma.Multiaddr {
 | 
						|
	// TODO: We should be able to do this directly without converting to/from a string.
 | 
						|
	relayAddr, err := ma.NewComponent(
 | 
						|
		ma.ProtocolWithCode(ma.P_P2P).Name,
 | 
						|
		c.stream.Conn().RemotePeer().String(),
 | 
						|
	)
 | 
						|
	if err != nil {
 | 
						|
		panic(err)
 | 
						|
	}
 | 
						|
	return ma.Join(c.stream.Conn().RemoteMultiaddr(), relayAddr, circuitAddr)
 | 
						|
}
 | 
						|
 | 
						|
func (c *Conn) LocalMultiaddr() ma.Multiaddr {
 | 
						|
	return c.stream.Conn().LocalMultiaddr()
 | 
						|
}
 | 
						|
 | 
						|
func (c *Conn) LocalAddr() net.Addr {
 | 
						|
	na, err := manet.ToNetAddr(c.stream.Conn().LocalMultiaddr())
 | 
						|
	if err != nil {
 | 
						|
		log.Error("failed to convert local multiaddr to net addr:", err)
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	return na
 | 
						|
}
 | 
						|
 | 
						|
func (c *Conn) RemoteAddr() net.Addr {
 | 
						|
	return &NetAddr{
 | 
						|
		Relay:  c.stream.Conn().RemotePeer().String(),
 | 
						|
		Remote: c.remote.ID.String(),
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// ConnStat interface
 | 
						|
var _ network.ConnStat = (*Conn)(nil)
 | 
						|
 | 
						|
func (c *Conn) Stat() network.ConnStats {
 | 
						|
	return c.stat
 | 
						|
}
 | 
						|
 | 
						|
// tagHop tags the underlying relay connection so that it can be (somewhat) protected from the
 | 
						|
// connection manager as it is an important connection that proxies other connections.
 | 
						|
// This is handled here so that the user code doesnt need to bother with this and avoid
 | 
						|
// clown shoes situations where a high value peer connection is behind a relayed connection and it is
 | 
						|
// implicitly because the connection manager closed the underlying relay connection.
 | 
						|
func (c *Conn) tagHop() {
 | 
						|
	c.client.mx.Lock()
 | 
						|
	defer c.client.mx.Unlock()
 | 
						|
 | 
						|
	p := c.stream.Conn().RemotePeer()
 | 
						|
	c.client.hopCount[p]++
 | 
						|
	if c.client.hopCount[p] == 1 {
 | 
						|
		c.client.host.ConnManager().TagPeer(p, "relay-hop-stream", HopTagWeight)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// untagHop removes the relay-hop-stream tag if necessary; it is invoked when a relayed connection
 | 
						|
// is closed.
 | 
						|
func (c *Conn) untagHop() {
 | 
						|
	c.client.mx.Lock()
 | 
						|
	defer c.client.mx.Unlock()
 | 
						|
 | 
						|
	p := c.stream.Conn().RemotePeer()
 | 
						|
	c.client.hopCount[p]--
 | 
						|
	if c.client.hopCount[p] == 0 {
 | 
						|
		c.client.host.ConnManager().UntagPeer(p, "relay-hop-stream")
 | 
						|
		delete(c.client.hopCount, p)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
type capableConnWithStat interface {
 | 
						|
	tpt.CapableConn
 | 
						|
	network.ConnStat
 | 
						|
}
 | 
						|
 | 
						|
type capableConn struct {
 | 
						|
	capableConnWithStat
 | 
						|
}
 | 
						|
 | 
						|
var transportName = ma.ProtocolWithCode(ma.P_CIRCUIT).Name
 | 
						|
 | 
						|
func (c capableConn) ConnState() network.ConnectionState {
 | 
						|
	return network.ConnectionState{
 | 
						|
		Transport: transportName,
 | 
						|
	}
 | 
						|
}
 |