forked from iriscouch/dnsd
-
Notifications
You must be signed in to change notification settings - Fork 4
/
convenient.js
129 lines (97 loc) · 3.39 KB
/
convenient.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// Copyright 2012 Iris Couch, all rights reserved.
//
// Convenience routines to make it easier to build a service
require('defaultable')(module,
{ 'convenient' : true
, 'ttl' : 3600
}, function(module, exports, DEFS, require) {
function noop() {}
module.exports = { 'init_response' : init_response
, 'final_response': final_response
, 'seconds': seconds
, 'serial': serial
}
if(! DEFS.convenient) {
module.exports.init_response = noop
module.exports.final_response = noop
}
function init_response(res) {
res.type = 'response'
}
function final_response(res, value) {
if(Array.isArray(value)) {
res.answer = (res.answer || []).concat(value)
value = undefined
} else if(typeof value == 'object') {
res = new res.constructor(value, value.connection || res.connection)
value = undefined
}
var questions = res.question || []
, answers = res.answer || []
, authorities = res.authority || []
, additionals = res.additional || []
res.recursion_available = false
// Find the zone of authority for this record, if any.
var question = questions[0]
, names = question && question.name && question.name.split(/\./)
, zone, soa_record
while(names && names.length) {
zone = names.join('.')
names.shift()
soa_record = res.connection.server.zones[zone]
if(soa_record)
break
}
res.authoritative = !! soa_record
// Add convenience for typical name resolution.
if(questions.length == 1 && question.kind() == 'IN A') {
// If the value given is an IP address, make that the answer.
if(typeof value == 'string' && answers.length == 0)
res.answer.push({'class':'IN', 'type':'A', 'name':question.name, 'data':value})
}
// Convenience for SOA queries
else if(questions.length == 1 && question.kind() == 'IN SOA') {
// Respond with the SOA record for this zone if necessary and possible.
if(answers.length == 0 && soa_record && soa_record.name == question.name)
res.answer.push(soa_record)
}
// If the server is authoritative for a zone, add an SOA record if there is no good answer.
if(soa_record && questions.length == 1 && answers.length == 0 && authorities.length == 0)
res.authority.push(soa_record)
// Set missing TTLs
answers.forEach(well_formed_record)
authorities.forEach(well_formed_record)
additionals.forEach(well_formed_record)
return res
function well_formed_record(record) {
record.class = record.class || 'IN'
var zone_minimum = DEFS.ttl
if(soa_record)
zone_minimum = soa_record.data.ttl
record.ttl = Math.max(record.ttl || 0, zone_minimum)
}
}
function serial(value) {
if(value != 'now')
return value
// Otherwise, "now" is the current Unix time (no milliseconds).
var now = new Date
return Math.floor(now.getTime() / 1000)
}
// Convert various string values to seconds.
function seconds(value) {
if(typeof value != 'string')
return value
var match
if(match = value.match(/^(\d+)s$/)) // seconds
return +match[1]
if(match = value.match(/^(\d+)m$/)) // minutes
return +match[1] * 60
if(match = value.match(/^(\d+)h$/)) // hours
return +match[1] * 60 * 60
if(match = value.match(/^(\d+)d$/)) // days
return +match[1] * 60 * 60 * 24
if(match = value.match(/^(\d+)w$/)) // weeks
return +match[1] * 60 * 60 * 24 * 7
}
}) // defaultable