mirror of
				https://source.quilibrium.com/quilibrium/ceremonyclient.git
				synced 2025-11-04 00:27:41 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			114 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			114 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package libp2pwebtransport
 | 
						|
 | 
						|
import (
 | 
						|
	"errors"
 | 
						|
	"fmt"
 | 
						|
	"net"
 | 
						|
	"strconv"
 | 
						|
 | 
						|
	ma "github.com/multiformats/go-multiaddr"
 | 
						|
	manet "github.com/multiformats/go-multiaddr/net"
 | 
						|
	"github.com/multiformats/go-multibase"
 | 
						|
	"github.com/multiformats/go-multihash"
 | 
						|
)
 | 
						|
 | 
						|
var webtransportMA = ma.StringCast("/quic-v1/webtransport")
 | 
						|
 | 
						|
func toWebtransportMultiaddr(na net.Addr) (ma.Multiaddr, error) {
 | 
						|
	addr, err := manet.FromNetAddr(na)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	if _, err := addr.ValueForProtocol(ma.P_UDP); err != nil {
 | 
						|
		return nil, errors.New("not a UDP address")
 | 
						|
	}
 | 
						|
	return addr.Encapsulate(webtransportMA), nil
 | 
						|
}
 | 
						|
 | 
						|
func stringToWebtransportMultiaddr(str string) (ma.Multiaddr, error) {
 | 
						|
	host, portStr, err := net.SplitHostPort(str)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	port, err := strconv.ParseInt(portStr, 10, 32)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	ip := net.ParseIP(host)
 | 
						|
	if ip == nil {
 | 
						|
		return nil, errors.New("failed to parse IP")
 | 
						|
	}
 | 
						|
	return toWebtransportMultiaddr(&net.UDPAddr{IP: ip, Port: int(port)})
 | 
						|
}
 | 
						|
 | 
						|
func extractCertHashes(addr ma.Multiaddr) ([]multihash.DecodedMultihash, error) {
 | 
						|
	certHashesStr := make([]string, 0, 2)
 | 
						|
	ma.ForEach(addr, func(c ma.Component) bool {
 | 
						|
		if c.Protocol().Code == ma.P_CERTHASH {
 | 
						|
			certHashesStr = append(certHashesStr, c.Value())
 | 
						|
		}
 | 
						|
		return true
 | 
						|
	})
 | 
						|
	certHashes := make([]multihash.DecodedMultihash, 0, len(certHashesStr))
 | 
						|
	for _, s := range certHashesStr {
 | 
						|
		_, ch, err := multibase.Decode(s)
 | 
						|
		if err != nil {
 | 
						|
			return nil, fmt.Errorf("failed to multibase-decode certificate hash: %w", err)
 | 
						|
		}
 | 
						|
		dh, err := multihash.Decode(ch)
 | 
						|
		if err != nil {
 | 
						|
			return nil, fmt.Errorf("failed to multihash-decode certificate hash: %w", err)
 | 
						|
		}
 | 
						|
		certHashes = append(certHashes, *dh)
 | 
						|
	}
 | 
						|
	return certHashes, nil
 | 
						|
}
 | 
						|
 | 
						|
func addrComponentForCert(hash []byte) (ma.Multiaddr, error) {
 | 
						|
	mh, err := multihash.Encode(hash, multihash.SHA2_256)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	certStr, err := multibase.Encode(multibase.Base58BTC, mh)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	return ma.NewComponent(ma.ProtocolWithCode(ma.P_CERTHASH).Name, certStr)
 | 
						|
}
 | 
						|
 | 
						|
// IsWebtransportMultiaddr returns true if the given multiaddr is a well formed
 | 
						|
// webtransport multiaddr. Returns the number of certhashes found.
 | 
						|
func IsWebtransportMultiaddr(multiaddr ma.Multiaddr) (bool, int) {
 | 
						|
	const (
 | 
						|
		init = iota
 | 
						|
		foundUDP
 | 
						|
		foundQuicV1
 | 
						|
		foundWebTransport
 | 
						|
	)
 | 
						|
	state := init
 | 
						|
	certhashCount := 0
 | 
						|
 | 
						|
	ma.ForEach(multiaddr, func(c ma.Component) bool {
 | 
						|
		switch c.Protocol().Code {
 | 
						|
		case ma.P_UDP:
 | 
						|
			if state == init {
 | 
						|
				state = foundUDP
 | 
						|
			}
 | 
						|
		case ma.P_QUIC_V1:
 | 
						|
			if state == foundUDP {
 | 
						|
				state = foundQuicV1
 | 
						|
			}
 | 
						|
		case ma.P_WEBTRANSPORT:
 | 
						|
			if state == foundQuicV1 {
 | 
						|
				state = foundWebTransport
 | 
						|
			}
 | 
						|
		case ma.P_CERTHASH:
 | 
						|
			if state == foundWebTransport {
 | 
						|
				certhashCount++
 | 
						|
			}
 | 
						|
		}
 | 
						|
		return true
 | 
						|
	})
 | 
						|
	return state == foundWebTransport, certhashCount
 | 
						|
}
 |