Make dns resolve paths under _dnslink.
Thus allowing to CNAME main site entry to gateway and stil specify dnslink. License: MIT Signed-off-by: Jakub Sztandera <kubuxu@gmail.com>
Kubuxu committed
Jan 11, 2016 at 16:01 UTC
0e18246294bba0cba7055ebfb3058e82e78c2881
2 files changed
+81
-10
namesys/dns.go
+53
-10
@@ -41,33 +41,76 @@ func (r *DNSResolver) ResolveN(ctx context.Context, name string, depth int) (pat
41
return resolve(ctx, r, name, depth, "/ipns/")
42
}
43
44
+type lookupRes struct {
45
+ path path.Path
46
+ error error
47
+}
48
+
49
// resolveOnce implements resolver.
50
// TXT records for a given domain name should contain a b58
51
// encoded multihash.
52
func (r *DNSResolver) resolveOnce(ctx context.Context, name string) (path.Path, error) {
53
segments := strings.SplitN(name, "/", 2)
54
+ domain := segments[0]
55
50
- if !isd.IsDomain(segments[0]) {
56
+ if !isd.IsDomain(domain) {
57
return "", errors.New("not a valid domain name")
58
}
59
+ log.Infof("DNSResolver resolving %s", domain)
60
+
61
+ rootChan := make(chan lookupRes, 1)
62
+ go workDomain(r, domain, rootChan)
63
+
64
+ subChan := make(chan lookupRes, 1)
65
+ go workDomain(r, "_dnslink."+domain, subChan)
66
+
67
+ var subRes lookupRes
68
+ select {
69
+ case subRes = <-subChan:
70
+ case <-ctx.Done():
71
+ return "", ctx.Err()
72
+ }
73
+
74
+ var p path.Path
75
+ if subRes.error == nil {
76
+ p = subRes.path
77
+ } else {
78
+ var rootRes lookupRes
79
+ select {
80
+ case rootRes = <-rootChan:
81
+ case <-ctx.Done():
82
+ return "", ctx.Err()
83
+ }
84
+ if rootRes.error == nil {
85
+ p = rootRes.path
86
+ } else {
87
+ return "", ErrResolveFailed
88
+ }
89
+ }
90
+ if len(segments) > 1 {
91
+ return path.FromSegments("", strings.TrimRight(p.String(), "/"), segments[1])
92
+ } else {
93
+ return p, nil
94
+ }
95
+}
96
+
97
+func workDomain(r *DNSResolver, name string, res chan lookupRes) {
98
+ txt, err := r.lookupTXT(name)
99
54
- log.Infof("DNSResolver resolving %s", segments[0])
55
- txt, err := r.lookupTXT(segments[0])
100
if err != nil {
57
- return "", err
101
+ // Error is != nil
102
+ res <- lookupRes{"", err}
103
+ return
104
}
105
106
for _, t := range txt {
107
p, err := parseEntry(t)
108
if err == nil {
63
- if len(segments) > 1 {
64
- return path.FromSegments("", strings.TrimRight(p.String(), "/"), segments[1])
65
- }
66
- return p, nil
109
+ res <- lookupRes{p, nil}
110
+ return
111
}
112
}
69
-
70
- return "", ErrResolveFailed
113
+ res <- lookupRes{"", ErrResolveFailed}
114
}
115
116
func parseEntry(txt string) (path.Path, error) {
namesys/dns_test.go
+28
@@ -65,6 +65,9 @@ func newMockDNS() *mockDNS {
65
"ipfs.example.com": []string{
66
"dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD",
67
},
68
+ "_dnslink.dipfs.example.com": []string{
69
+ "dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD",
70
+ },
71
"dns1.example.com": []string{
72
"dnslink=/ipns/ipfs.example.com",
73
},
@@ -85,6 +88,12 @@ func newMockDNS() *mockDNS {
88
"loop2.example.com": []string{
89
"dnslink=/ipns/loop1.example.com",
90
},
91
+ "_dnslink.dloop1.example.com": []string{
92
+ "dnslink=/ipns/loop2.example.com",
93
+ },
94
+ "_dnslink.dloop2.example.com": []string{
95
+ "dnslink=/ipns/loop1.example.com",
96
+ },
97
"bad.example.com": []string{
98
"dnslink=",
99
},
@@ -100,6 +109,18 @@ func newMockDNS() *mockDNS {
109
"withtrailingrec.example.com": []string{
110
"dnslink=/ipns/withtrailing.example.com/segment/",
111
},
112
+ "double.example.com": []string{
113
+ "dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD",
114
+ },
115
+ "_dnslink.double.example.com": []string{
116
+ "dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD",
117
+ },
118
+ "double.conflict.com": []string{
119
+ "dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD",
120
+ },
121
+ "_dnslink.conflict.example.com": []string{
122
+ "dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjE",
123
+ },
124
},
125
}
126
}
@@ -109,6 +130,7 @@ func TestDNSResolution(t *testing.T) {
130
r := &DNSResolver{lookupTXT: mock.lookupTXT}
131
testResolution(t, r, "multihash.example.com", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil)
132
testResolution(t, r, "ipfs.example.com", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil)
133
+ testResolution(t, r, "dipfs.example.com", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil)
134
testResolution(t, r, "dns1.example.com", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil)
135
testResolution(t, r, "dns1.example.com", 1, "/ipns/ipfs.example.com", ErrResolveRecursion)
136
testResolution(t, r, "dns2.example.com", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil)
@@ -122,6 +144,10 @@ func TestDNSResolution(t *testing.T) {
144
testResolution(t, r, "loop1.example.com", 2, "/ipns/loop1.example.com", ErrResolveRecursion)
145
testResolution(t, r, "loop1.example.com", 3, "/ipns/loop2.example.com", ErrResolveRecursion)
146
testResolution(t, r, "loop1.example.com", DefaultDepthLimit, "/ipns/loop1.example.com", ErrResolveRecursion)
147
+ testResolution(t, r, "dloop1.example.com", 1, "/ipns/loop2.example.com", ErrResolveRecursion)
148
+ testResolution(t, r, "dloop1.example.com", 2, "/ipns/loop1.example.com", ErrResolveRecursion)
149
+ testResolution(t, r, "dloop1.example.com", 3, "/ipns/loop2.example.com", ErrResolveRecursion)
150
+ testResolution(t, r, "dloop1.example.com", DefaultDepthLimit, "/ipns/loop1.example.com", ErrResolveRecursion)
151
testResolution(t, r, "bad.example.com", DefaultDepthLimit, "", ErrResolveFailed)
152
testResolution(t, r, "withsegment.example.com", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/sub/segment", nil)
153
testResolution(t, r, "withrecsegment.example.com", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/sub/segment/subsub", nil)
@@ -129,4 +155,6 @@ func TestDNSResolution(t *testing.T) {
155
testResolution(t, r, "withrecsegment.example.com/test2", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/sub/segment/subsub/test2", nil)
156
testResolution(t, r, "withrecsegment.example.com/test3/", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/sub/segment/subsub/test3/", nil)
157
testResolution(t, r, "withtrailingrec.example.com", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/sub/segment/", nil)
158
+ testResolution(t, r, "double.example.com", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil)
159
+ testResolution(t, r, "conflict.example.com", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjE", nil)
160
}