-
Notifications
You must be signed in to change notification settings - Fork 106
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f950a79
commit 41befc7
Showing
8 changed files
with
120 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* eslint-env mocha */ | ||
|
||
import { ipns } from '@helia/ipns' | ||
import { createHeliaNode } from './fixtures/create-helia.js' | ||
import type { IPNS } from '@helia/ipns' | ||
import type { HeliaLibp2p } from 'helia' | ||
|
||
describe.only('@helia/ipns - dnslink', () => { | ||
let helia: HeliaLibp2p | ||
let name: IPNS | ||
|
||
beforeEach(async () => { | ||
helia = await createHeliaNode() | ||
name = ipns(helia) | ||
}) | ||
|
||
afterEach(async () => { | ||
if (helia != null) { | ||
await helia.stop() | ||
} | ||
}) | ||
|
||
it('should resolve ipfs.io', async () => { | ||
const result = await name.resolveDns('ipfs.io') | ||
|
||
console.info(result) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import { CodeError, type Logger } from '@libp2p/interface' | ||
import { peerIdFromString } from '@libp2p/peer-id' | ||
import { RecordType } from '@multiformats/dns' | ||
import { CID } from 'multiformats/cid' | ||
import type { ResolveDNSOptions } from './index.js' | ||
import type { DNS } from '@multiformats/dns' | ||
|
||
const MAX_RECURSIVE_DEPTH = 32 | ||
|
||
export const recursiveResolveDnslink = async (domain: string, depth: number, dns: DNS, log: Logger, options: ResolveDNSOptions = {}): Promise<string> => { | ||
if (depth === 0) { | ||
throw new Error('recursion limit exceeded') | ||
} | ||
|
||
const response = await dns.query(domain, { | ||
...options, | ||
types: [ | ||
RecordType.TXT | ||
] | ||
}) | ||
|
||
// TODO: support multiple dnslink records | ||
for (const answer of response.Answer) { | ||
try { | ||
let result = answer.data | ||
|
||
if (!result.startsWith('dnslink=')) { | ||
// invalid record? | ||
continue | ||
} | ||
|
||
result = result.replace('dnslink=', '') | ||
// result is now a `/ipfs/<cid>` or `/ipns/<cid>` string | ||
const [, protocol, domainOrCID, ...rest] = result.split('/') // e.g. ["", "ipfs", "<cid>"] | ||
|
||
if (protocol === 'ipfs') { | ||
try { | ||
const cid = CID.parse(domainOrCID) | ||
|
||
// if the result is a CID, we've reached the end of the recursion | ||
return `/ipfs/${cid}${rest.length > 0 ? `/${rest.join('/')}` : ''}` | ||
} catch {} | ||
} else if (protocol === 'ipns') { | ||
try { | ||
const peerId = peerIdFromString(domainOrCID) | ||
|
||
// if the result is a PeerId, we've reached the end of the recursion | ||
return `/ipns/${peerId}${rest.length > 0 ? `/${rest.join('/')}` : ''}` | ||
} catch {} | ||
|
||
// if the result was another IPNS domain, try to follow it | ||
return await recursiveResolveDnslink(domainOrCID, depth - 1, dns, log, options) | ||
} else { | ||
throw new CodeError(`Unknown protocol in DNSLink record for domain: ${domain}`, 'ERR_DNSLINK_NOT_FOUND') | ||
} | ||
} catch (err: any) { | ||
log.error('could not parse DNS link record for domain %s, %s', domain, answer.data, err) | ||
} | ||
} | ||
|
||
throw new CodeError(`No DNSLink records found for domain: ${domain}`, 'ERR_DNSLINK_NOT_FOUND') | ||
} | ||
|
||
export async function resolveDNSLink (domain: string, dns: DNS, log: Logger, options: ResolveDNSOptions = {}): Promise<string> { | ||
try { | ||
return await recursiveResolveDnslink(domain, options.maxRecursiveDepth ?? MAX_RECURSIVE_DEPTH, dns, log, options) | ||
} catch (err: any) { | ||
// If the code is not ENOTFOUND or ERR_DNSLINK_NOT_FOUND or ENODATA then throw the error | ||
if (err.code !== 'ENOTFOUND' && err.code !== 'ERR_DNSLINK_NOT_FOUND' && err.code !== 'ENODATA') { | ||
throw err | ||
} | ||
|
||
if (domain.startsWith('_dnslink.')) { | ||
// The supplied domain contains a _dnslink component | ||
// Check the non-_dnslink domain | ||
domain = domain.replace('_dnslink.', '') | ||
} else { | ||
// Check the _dnslink subdomain | ||
domain = `_dnslink.${domain}` | ||
} | ||
|
||
// If this throws then we propagate the error | ||
return await recursiveResolveDnslink(domain, options.maxRecursiveDepth ?? MAX_RECURSIVE_DEPTH, dns, log, options) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters