9 ma "github.com/multiformats/go-multiaddr"
12 var ResolvableProtocols = []ma.Protocol{DnsaddrProtocol, Dns4Protocol, Dns6Protocol}
13 var DefaultResolver = &Resolver{Backend: net.DefaultResolver}
15 type backend interface {
16 LookupIPAddr(context.Context, string) ([]net.IPAddr, error)
17 LookupTXT(context.Context, string) ([]string, error)
20 type Resolver struct {
24 type MockBackend struct {
25 IP map[string][]net.IPAddr
26 TXT map[string][]string
29 func (r *MockBackend) LookupIPAddr(ctx context.Context, name string) ([]net.IPAddr, error) {
30 results, ok := r.IP[name]
34 return []net.IPAddr{}, nil
38 func (r *MockBackend) LookupTXT(ctx context.Context, name string) ([]string, error) {
39 results, ok := r.TXT[name]
43 return []string{}, nil
47 func Matches(maddr ma.Multiaddr) bool {
48 protos := maddr.Protocols()
53 for _, p := range ResolvableProtocols {
54 if protos[0].Code == p.Code {
62 func Resolve(ctx context.Context, maddr ma.Multiaddr) ([]ma.Multiaddr, error) {
63 return DefaultResolver.Resolve(ctx, maddr)
66 func (r *Resolver) Resolve(ctx context.Context, maddr ma.Multiaddr) ([]ma.Multiaddr, error) {
68 return []ma.Multiaddr{maddr}, nil
71 protos := maddr.Protocols()
72 if protos[0].Code == Dns4Protocol.Code {
73 return r.resolveDns4(ctx, maddr)
75 if protos[0].Code == Dns6Protocol.Code {
76 return r.resolveDns6(ctx, maddr)
78 if protos[0].Code == DnsaddrProtocol.Code {
79 return r.resolveDnsaddr(ctx, maddr)
85 func (r *Resolver) resolveDns4(ctx context.Context, maddr ma.Multiaddr) ([]ma.Multiaddr, error) {
86 value, err := maddr.ValueForProtocol(Dns4Protocol.Code)
88 return nil, fmt.Errorf("error resolving %s: %s", maddr.String(), err)
91 encap := ma.Split(maddr)[1:]
93 result := []ma.Multiaddr{}
94 records, err := r.Backend.LookupIPAddr(ctx, value)
99 for _, r := range records {
104 ip4maddr, err := ma.NewMultiaddr("/ip4/" + ip4.String())
108 parts := append([]ma.Multiaddr{ip4maddr}, encap...)
109 result = append(result, ma.Join(parts...))
114 func (r *Resolver) resolveDns6(ctx context.Context, maddr ma.Multiaddr) ([]ma.Multiaddr, error) {
115 value, err := maddr.ValueForProtocol(Dns6Protocol.Code)
117 return nil, fmt.Errorf("error resolving %s: %s", maddr.String(), err)
120 encap := ma.Split(maddr)[1:]
122 result := []ma.Multiaddr{}
123 records, err := r.Backend.LookupIPAddr(ctx, value)
128 for _, r := range records {
129 if r.IP.To4() != nil {
132 ip6maddr, err := ma.NewMultiaddr("/ip6/" + r.IP.To16().String())
136 parts := append([]ma.Multiaddr{ip6maddr}, encap...)
137 result = append(result, ma.Join(parts...))
142 func (r *Resolver) resolveDnsaddr(ctx context.Context, maddr ma.Multiaddr) ([]ma.Multiaddr, error) {
143 value, err := maddr.ValueForProtocol(DnsaddrProtocol.Code)
145 return nil, fmt.Errorf("error resolving %s: %s", maddr.String(), err)
148 trailer := ma.Split(maddr)[1:]
150 result := []ma.Multiaddr{}
151 records, err := r.Backend.LookupTXT(ctx, "_dnsaddr."+value)
156 for _, r := range records {
157 rv := strings.Split(r, "dnsaddr=")
162 rmaddr, err := ma.NewMultiaddr(rv[1])
167 if matchDnsaddr(rmaddr, trailer) {
168 result = append(result, rmaddr)
174 // XXX probably insecure
175 func matchDnsaddr(maddr ma.Multiaddr, trailer []ma.Multiaddr) bool {
176 parts := ma.Split(maddr)
177 if ma.Join(parts[len(parts)-len(trailer):]...).Equal(ma.Join(trailer...)) {