Commit d3027fee807fce808aec9f7948f0719338d790e2
Merge branch 'show-cmd'
ansuz committed on 11/25/2016, 10:37:44 PMParent: c24fdc18c3deb086c2ba4086840b4abf85b6376c
Parent: a916aab11e0c6b05c831a6cb93d1754faf91e9d1
Files changed
index.js | changed |
lib/dump.js | changed |
lib/index.js | changed |
lib/query.js | changed |
lib/server.js | changed |
lib/format.js | added |
package.json | changed |
index.js | ||
---|---|---|
@@ -12,8 +12,9 @@ | ||
12 | 12 … | var updateHelp = "\tdnssb update name [ttl] [class] type value"; |
13 | 13 … | var branchHelp = "\tdnssb branch name type (class)"; |
14 | 14 … | var serverHelp = "\tdnssb server port host"; |
15 | 15 … | var dumpHelp = "\tdnssb dump"; |
16 … | +var showHelp = "\tdnssb show [domain]"; | |
16 | 17 … | |
17 | 18 … | var CLI_Help = function () { |
18 | 19 … | [ |
19 | 20 … | "try one of:", |
@@ -21,8 +22,9 @@ | ||
21 | 22 … | publishHelp, |
22 | 23 … | updateHelp, |
23 | 24 … | branchHelp, |
24 | 25 … | dumpHelp, |
26 … | + showHelp, | |
25 | 27 … | ].forEach(function (m) { |
26 | 28 … | console.log(m); |
27 | 29 … | }); |
28 | 30 … | }; |
@@ -34,18 +36,42 @@ | ||
34 | 36 … | CLI_Help(); |
35 | 37 … | break; |
36 | 38 … | case 'dump': |
37 | 39 … | (function () { |
38 | - var count = 0; | |
39 | - Lib.dump.records(function (record) { // each | |
40 | - console.log(JSON.stringify(record, null, 2)); | |
41 | - count++; | |
42 | - }, function (sbot) { // done | |
43 | - console.log("Found a total of %s valid ssb-dns records", count); | |
44 | - sbot.close(); | |
40 … | + var Client = require("ssb-client"); | |
41 … | + | |
42 … | + Client(function (err, sbot) { | |
43 … | + if (err) throw err; | |
44 … | + | |
45 … | + var count = 0; | |
46 … | + Lib.dump.records(sbot, function (record) { // each | |
47 … | + console.log(JSON.stringify(record, null, 2)); | |
48 … | + count++; | |
49 … | + }, function (err) { // done | |
50 … | + if (err) throw err; | |
51 … | + console.log("Found a total of %s valid ssb-dns records", count); | |
52 … | + sbot.close(); | |
53 … | + }); | |
45 | 54 … | }); |
46 | 55 … | }()); |
47 | 56 … | break; |
57 … | + case 'show': | |
58 … | + (function () { | |
59 … | + var name = argv[1] || ''; | |
60 … | + var Client = require("ssb-client"); | |
61 … | + | |
62 … | + Client(function (err, sbot) { | |
63 … | + if (err) throw err; | |
64 … | + | |
65 … | + Lib.dump.formattedRecords(sbot, {name: name}, function (line) { | |
66 … | + console.log(line); | |
67 … | + }, function (err) { // done | |
68 … | + if (err) throw err; | |
69 … | + sbot.close(); | |
70 … | + }); | |
71 … | + }); | |
72 … | + }()); | |
73 … | + break; | |
48 | 74 … | case 'server': |
49 | 75 … | (function () { |
50 | 76 … | var port = argv[1] || 53053; |
51 | 77 … | var host = argv[2] || '127.0.0.1'; |
lib/dump.js | ||
---|---|---|
@@ -1,22 +1,52 @@ | ||
1 | 1 … | var Pull = require("pull-stream"); |
2 … | +var Paramap = require("pull-paramap"); | |
3 … | +var AsyncMemo = require("asyncmemo"); | |
4 … | +var getAvatar = require("ssb-avatar"); | |
2 | 5 … | var Query = require("./query"); |
6 … | +var Format = require("./format"); | |
3 | 7 … | var Dump = module.exports = {}; |
4 | 8 … | |
5 | -Dump.records = function (each, done) { | |
6 | - var Client = require("ssb-client"); | |
9 … | +Dump.records = function (sbot, each, done) { | |
10 … | + Pull(Query.all(sbot), | |
11 … | + Query.drainSet(each, done)); | |
12 … | +}; | |
7 | 13 … | |
8 | - Client(function (err, sbot) { | |
9 | - if (err) { return void done(err); } | |
14 … | +function sortRecords(records) { | |
15 … | + records.forEach(function (r) { | |
16 … | + r.labels = typeof r.name === 'string' | |
17 … | + ? r.name.split(/\./).reverse() : []; | |
18 … | + }); | |
19 … | + records.sort(function (a, b) { | |
20 … | + var len = Math.max(a.labels.length, b.labels.length); | |
21 … | + for (var i = 0; i < len; i++) { | |
22 … | + var labA = a.labels[i] || ''; | |
23 … | + var labB = b.labels[i] || ''; | |
24 … | + if (labA > labB) return 1; | |
25 … | + if (labA < labB) return -1; | |
26 … | + } | |
27 … | + return 0; | |
28 … | + }) | |
29 … | +} | |
10 | 30 … | |
11 | - Pull(Query.all(sbot), | |
12 | - Query.drainSet(each, function (err) { | |
13 | - if (err) throw err; | |
14 | - done(sbot); | |
31 … | +Dump.formattedRecords = function (sbot, opts, each, done) { | |
32 … | + sbot.whoami(function (err, feed) { | |
33 … | + if (err) throw err; | |
34 … | + var getAbout = AsyncMemo(getAvatar, sbot, feed.id); | |
35 … | + | |
36 … | + Pull(Query.inDomain(sbot, opts.name), | |
37 … | + Query.collectSet(function (err, records) { | |
38 … | + if (err) throw err; | |
39 … | + records.forEach(Format.formatNames(opts.name)); | |
40 … | + sortRecords(records); | |
41 … | + Pull(Pull.values(records), | |
42 … | + Paramap(function (record, cb) { | |
43 … | + getAbout(record.author, function (err, about) { | |
44 … | + record.authorName = '@' + about.name; | |
45 … | + cb(err, record); | |
46 … | + }); | |
47 … | + }, 8), | |
48 … | + Pull.map(Format.recordsToLines(Format.getMaxLengths(records))), | |
49 … | + Pull.drain(each, done)) | |
15 | 50 … | })); |
16 | 51 … | }); |
17 | 52 … | }; |
18 | - | |
19 | -Dump.recordToLine = function (record) { | |
20 | - // TODO: output in zone-file-like format | |
21 | - return JSON.stringify(record); | |
22 | -}; |
lib/index.js | ||
---|---|---|
@@ -9,8 +9,10 @@ | ||
9 | 9 … | Lib.query = require("./query"); |
10 | 10 … | |
11 | 11 … | Lib.parse = require("./parse"); |
12 | 12 … | |
13 … | +Lib.format = require("./format"); | |
14 … | + | |
13 | 15 … | // run as a scuttlebot plugin |
14 | 16 … | var plugin = Lib; |
15 | 17 … | var pkg = require("../package"); |
16 | 18 … | plugin.name = "dns"; |
lib/query.js | ||
---|---|---|
@@ -41,8 +41,47 @@ | ||
41 | 41 … | Pull.map(msgToRecord), |
42 | 42 … | Pull.filter()); |
43 | 43 … | }; |
44 | 44 … | |
45 … | +function recordsInDomain(sbot, name) { | |
46 … | + var path = name.split(/\./g).reverse() | |
47 … | + | |
48 … | + /* enable this when records without path propery are to be deprecated: | |
49 … | + // use ssb-query if it is supported | |
50 … | + if (sbot.query) return sbot.query.read({ | |
51 … | + query: [{$filter: {value: {content: { | |
52 … | + type: 'ssb-dns', | |
53 … | + path: {$prefix: path} | |
54 … | + }}}}] | |
55 … | + }); | |
56 … | + */ | |
57 … | + | |
58 … | + // fallback to logt | |
59 … | + return Pull(sbot.messagesByType({ | |
60 … | + type: 'ssb-dns', | |
61 … | + }), | |
62 … | + Pull.filter(function (msg) { | |
63 … | + var c = msg.value.content; | |
64 … | + var p = c.path; | |
65 … | + if (!p) { | |
66 … | + var name = c.record && c.record.name; | |
67 … | + if (typeof name !== 'string') return false; | |
68 … | + p = name.split(/\./).reverse() | |
69 … | + } | |
70 … | + for (var i = 0; i < path.length; i++) { | |
71 … | + if (path[i] !== p[i]) return false; | |
72 … | + } | |
73 … | + return true; | |
74 … | + })); | |
75 … | +} | |
76 … | + | |
77 … | +Query.inDomain = function (sbot, name) { | |
78 … | + if (!name) return Query.all(sbot); | |
79 … | + return Pull(recordsInDomain(sbot, name), | |
80 … | + Pull.map(msgToRecord), | |
81 … | + Pull.filter()); | |
82 … | +}; | |
83 … | + | |
45 | 84 … | function expandName(name, wildcard) { |
46 | 85 … | var names = {}; |
47 | 86 … | for (var labels = name.split(/\./); labels.length; labels.shift()) { |
48 | 87 … | if (wildcard) labels[0] = wildcard; |
@@ -107,8 +146,17 @@ | ||
107 | 146 … | onEnd(null); |
108 | 147 … | }); |
109 | 148 … | }; |
110 | 149 … | |
150 … | +Query.collectSet = function (cb) { | |
151 … | + var records = []; | |
152 … | + return Query.drainSet(function (record) { | |
153 … | + records.push(record); | |
154 … | + }, function (err) { | |
155 … | + return cb(err, records); | |
156 … | + }); | |
157 … | +}; | |
158 … | + | |
111 | 159 … | Query.query = function (sbot, question, cb) { |
112 | 160 … | // look up records that match a question, including wildcard records |
113 | 161 … | // and zone authority records |
114 | 162 … | var authorityDomains = expandName(question.name); |
lib/server.js | ||
---|---|---|
@@ -1,8 +1,9 @@ | ||
1 | 1 … | var Pull = require("pull-stream"); |
2 | 2 … | var Ansuz = require("ansuz"); |
3 | 3 … | var Query = require("./query"); |
4 | 4 … | var Dump = require("./dump"); |
5 … | +var Format = require("./format"); | |
5 | 6 … | var Net = require("net"); |
6 | 7 … | var Pad = require("pad-ipv6"); |
7 | 8 … | |
8 | 9 … | var Server = module.exports = {}; |
@@ -47,10 +48,10 @@ | ||
47 | 48 … | res.responseCode = 3; // NXDOMAIN |
48 | 49 … | } |
49 | 50 … | } |
50 | 51 … | if (opt && opt.verbose) { |
51 | - var recs = records.map(Dump.recordToLine).join(", ") | |
52 | - var auths = authorities.map(Dump.recordToLine).join(", ") | |
52 … | + var recs = records.map(Format.recordToLine).join(", ") | |
53 … | + var auths = authorities.map(Format.recordToLine).join(", ") | |
53 | 54 … | console.log("%s: %s%s", q.name, recs, |
54 | 55 … | auths ? '. auths: ' : '', auths); |
55 | 56 … | } |
56 | 57 … | res.answer = result.answers; |
lib/format.js | ||
---|---|---|
@@ -1,0 +1,81 @@ | ||
1 … | +var Format = module.exports = {}; | |
2 … | +var Pull = require("pull-stream"); | |
3 … | + | |
4 … | +function pad(str, len) { | |
5 … | + if (Math.abs(len) < String(str).length) return str; | |
6 … | + if (len < 0) return (' ' + str).substr(len); | |
7 … | + if (len > 0) return (str + ' ').substr(0, len); | |
8 … | +} | |
9 … | + | |
10 … | +Format.formatNames = function (name) { | |
11 … | + if (!name) { | |
12 … | + // make record name absolute | |
13 … | + return function (record) { | |
14 … | + record.name = record.name.replace(/\.?$/, '.'); | |
15 … | + }; | |
16 … | + } | |
17 … | + // make records' names be relative to some domain | |
18 … | + if (/[^a-z0-9\-.]/.test(name)) { | |
19 … | + throw new TypeError('name has bad characters'); | |
20 … | + } | |
21 … | + var nameRegexp = new RegExp('(?:^|\\.)' + name.replace(/\./g, '\\.') + '$'); | |
22 … | + return function (record) { | |
23 … | + record.name = record.name.replace(nameRegexp, '') || '@'; | |
24 … | + }; | |
25 … | +}; | |
26 … | + | |
27 … | +Format.getMaxLengths = function (records) { | |
28 … | + var maxLengths = {}; | |
29 … | + records.forEach(function (record) { | |
30 … | + for (var k in record) { | |
31 … | + var len = String(record[k]).length | |
32 … | + if (len > ~~maxLengths[k]) maxLengths[k] = len; | |
33 … | + } | |
34 … | + }); | |
35 … | + return maxLengths; | |
36 … | +}; | |
37 … | + | |
38 … | +Format.recordsToLines = function (maxLengths) { | |
39 … | + return function (record) { | |
40 … | + return [ | |
41 … | + record.id, | |
42 … | + pad(record.authorName, 12), | |
43 … | + pad(record.name, -maxLengths.name), | |
44 … | + pad(record.ttl, -maxLengths.ttl), | |
45 … | + pad(record.class, maxLengths.class), | |
46 … | + pad(record.type, maxLengths.type), | |
47 … | + dataToString(record, record.data) | |
48 … | + ].join(' '); | |
49 … | + }; | |
50 … | +}; | |
51 … | + | |
52 … | +function dataToString(record, data) { | |
53 … | + switch (record.class + " " + record.type) { | |
54 … | + case "IN A": | |
55 … | + case "IN AAAA": | |
56 … | + case "IN NS": | |
57 … | + case "IN PTR": | |
58 … | + case "IN CNAME": | |
59 … | + return data; | |
60 … | + case "IN MX": | |
61 … | + return [].concat(data).join(" "); | |
62 … | + case "IN SOA": | |
63 … | + return [data.mname, data.rname, data.serial, | |
64 … | + data.refresh, data.retry, data.expire, data.ttl].join(" "); | |
65 … | + case "IN TXT": | |
66 … | + case "IN SPF": | |
67 … | + return [].concat(data).join(""); | |
68 … | + case "IN SRV": | |
69 … | + return [data.priority, data.weight, data.port, | |
70 … | + data.target].join(" "); | |
71 … | + case "IN DS": | |
72 … | + return [data.key_tag, data.algorithm, data.digest_type, | |
73 … | + data.digest].join(" "); | |
74 … | + case "IN SSHFP": | |
75 … | + return [data.algorithm, data.fp_type, data.fingerprint].join(" "); | |
76 … | + case "NONE A": | |
77 … | + return ""; | |
78 … | + default: | |
79 … | + return JSON.stringify(record.data); | |
80 … | + } | |
81 … | +} |
package.json | ||
---|---|---|
@@ -10,12 +10,16 @@ | ||
10 | 10 … | "scripts": { |
11 | 11 … | "test": "echo \"Error: no test specified\" && exit 1" |
12 | 12 … | }, |
13 | 13 … | "dependencies": { |
14 … | + "asyncmemo": "^0.1.0", | |
14 | 15 … | "ansuz": "0.0.14", |
15 | 16 … | "modern-dnsd": "^0.9.9", |
16 | 17 … | "kvset": "1.0.0", |
17 | 18 … | "pad-ipv6": "^1.0.2", |
19 … | + "pull-paramap": "^1.1.6", | |
20 … | + "pull-stream": "^3.4.5", | |
21 … | + "ssb-avatar": "^0.2.0", | |
18 | 22 … | "ssb-client": "^4.0.2", |
19 | 23 … | "ssb-ref": "^2.6.2" |
20 | 24 … | }, |
21 | 25 … | "keywords": [ |
Built with git-ssb-web