Haraka 3.1.1 → 3.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierignore +4 -0
- package/CONTRIBUTORS.md +5 -5
- package/Changes.md +62 -50
- package/Plugins.md +3 -1
- package/README.md +1 -1
- package/bin/haraka +475 -479
- package/config/outbound.ini +3 -0
- package/connection.js +1072 -1108
- package/docs/Connection.md +29 -30
- package/docs/CoreConfig.md +38 -39
- package/docs/CustomReturnCodes.md +0 -1
- package/docs/HAProxy.md +2 -2
- package/docs/Header.md +1 -1
- package/docs/Logging.md +29 -5
- package/docs/Outbound.md +93 -78
- package/docs/Plugins.md +103 -108
- package/docs/Transaction.md +49 -51
- package/docs/Tutorial.md +127 -143
- package/docs/deprecated/access.md +0 -1
- package/docs/deprecated/backscatterer.md +2 -3
- package/docs/deprecated/connect.rdns_access.md +18 -27
- package/docs/deprecated/data.headers.md +0 -1
- package/docs/deprecated/data.nomsgid.md +1 -2
- package/docs/deprecated/data.noreceived.md +1 -2
- package/docs/deprecated/data.rfc5322_header_checks.md +1 -2
- package/docs/deprecated/dkim_sign.md +13 -17
- package/docs/deprecated/dkim_verify.md +9 -17
- package/docs/deprecated/dnsbl.md +36 -38
- package/docs/deprecated/dnswl.md +41 -43
- package/docs/deprecated/lookup_rdns.strict.md +21 -34
- package/docs/deprecated/mail_from.access.md +17 -25
- package/docs/deprecated/mail_from.blocklist.md +9 -12
- package/docs/deprecated/mail_from.nobounces.md +1 -2
- package/docs/deprecated/rcpt_to.access.md +20 -27
- package/docs/deprecated/rcpt_to.blocklist.md +10 -13
- package/docs/deprecated/rcpt_to.routes.md +0 -1
- package/docs/deprecated/rdns.regexp.md +13 -15
- package/docs/plugins/aliases.md +89 -89
- package/docs/plugins/auth/auth_bridge.md +5 -7
- package/docs/plugins/auth/auth_ldap.md +11 -14
- package/docs/plugins/auth/auth_proxy.md +10 -12
- package/docs/plugins/auth/auth_vpopmaild.md +5 -6
- package/docs/plugins/auth/flat_file.md +4 -4
- package/docs/plugins/block_me.md +3 -3
- package/docs/plugins/data.signatures.md +1 -2
- package/docs/plugins/delay_deny.md +3 -4
- package/docs/plugins/max_unrecognized_commands.md +4 -4
- package/docs/plugins/prevent_credential_leaks.md +6 -6
- package/docs/plugins/process_title.md +18 -18
- package/docs/plugins/queue/deliver.md +2 -3
- package/docs/plugins/queue/discard.md +4 -4
- package/docs/plugins/queue/lmtp.md +1 -3
- package/docs/plugins/queue/qmail-queue.md +7 -9
- package/docs/plugins/queue/quarantine.md +16 -21
- package/docs/plugins/queue/rabbitmq.md +8 -11
- package/docs/plugins/queue/rabbitmq_amqplib.md +43 -39
- package/docs/plugins/queue/smtp_bridge.md +7 -10
- package/docs/plugins/queue/smtp_forward.md +42 -34
- package/docs/plugins/queue/smtp_proxy.md +30 -29
- package/docs/plugins/queue/test.md +1 -3
- package/docs/plugins/rcpt_to.in_host_list.md +6 -6
- package/docs/plugins/rcpt_to.max_count.md +1 -1
- package/docs/plugins/record_envelope_addresses.md +3 -3
- package/docs/plugins/reseed_rng.md +6 -6
- package/docs/plugins/status.md +9 -8
- package/docs/plugins/tarpit.md +7 -11
- package/docs/plugins/tls.md +12 -17
- package/docs/plugins/toobusy.md +4 -4
- package/docs/plugins/xclient.md +3 -3
- package/docs/tutorials/Migrating_from_v1_to_v2.md +19 -41
- package/docs/tutorials/SettingUpOutbound.md +6 -9
- package/endpoint.js +35 -38
- package/eslint.config.mjs +22 -19
- package/haraka.js +42 -47
- package/host_pool.js +75 -79
- package/http/html/404.html +45 -49
- package/http/html/index.html +39 -28
- package/http/package.json +2 -4
- package/line_socket.js +27 -28
- package/logger.js +182 -201
- package/outbound/client_pool.js +33 -33
- package/outbound/config.js +64 -59
- package/outbound/fsync_writestream.js +24 -25
- package/outbound/hmail.js +888 -835
- package/outbound/index.js +194 -187
- package/outbound/qfile.js +49 -52
- package/outbound/queue.js +197 -190
- package/outbound/timer_queue.js +41 -43
- package/outbound/tls.js +68 -61
- package/outbound/todo.js +11 -11
- package/package.json +32 -32
- package/plugins/.eslintrc.yaml +0 -1
- package/plugins/auth/auth_base.js +123 -127
- package/plugins/auth/auth_bridge.js +7 -7
- package/plugins/auth/auth_proxy.js +121 -126
- package/plugins/auth/auth_vpopmaild.js +84 -85
- package/plugins/auth/flat_file.js +18 -17
- package/plugins/block_me.js +31 -31
- package/plugins/data.signatures.js +13 -13
- package/plugins/delay_deny.js +65 -61
- package/plugins/prevent_credential_leaks.js +23 -23
- package/plugins/process_title.js +125 -128
- package/plugins/profile.js +5 -5
- package/plugins/queue/deliver.js +3 -3
- package/plugins/queue/discard.js +13 -14
- package/plugins/queue/lmtp.js +16 -17
- package/plugins/queue/qmail-queue.js +54 -55
- package/plugins/queue/quarantine.js +68 -70
- package/plugins/queue/rabbitmq.js +80 -87
- package/plugins/queue/rabbitmq_amqplib.js +75 -54
- package/plugins/queue/smtp_bridge.js +16 -16
- package/plugins/queue/smtp_forward.js +175 -179
- package/plugins/queue/smtp_proxy.js +69 -71
- package/plugins/queue/test.js +9 -9
- package/plugins/rcpt_to.host_list_base.js +30 -34
- package/plugins/rcpt_to.in_host_list.js +19 -19
- package/plugins/record_envelope_addresses.js +4 -4
- package/plugins/reseed_rng.js +4 -4
- package/plugins/status.js +90 -97
- package/plugins/tarpit.js +25 -14
- package/plugins/tls.js +68 -68
- package/plugins/toobusy.js +21 -23
- package/plugins/xclient.js +51 -53
- package/plugins.js +276 -293
- package/rfc1869.js +30 -35
- package/server.js +308 -299
- package/smtp_client.js +244 -228
- package/test/.eslintrc.yaml +0 -1
- package/test/connection.js +127 -134
- package/test/endpoint.js +53 -47
- package/test/fixtures/line_socket.js +12 -12
- package/test/fixtures/util_hmailitem.js +89 -85
- package/test/host_pool.js +90 -92
- package/test/installation/plugins/base_plugin.js +2 -2
- package/test/installation/plugins/folder_plugin/index.js +2 -3
- package/test/installation/plugins/inherits.js +3 -3
- package/test/installation/plugins/load_first.js +2 -3
- package/test/installation/plugins/plugin.js +1 -3
- package/test/installation/plugins/tls.js +2 -4
- package/test/logger.js +135 -116
- package/test/outbound/hmail.js +49 -35
- package/test/outbound/index.js +118 -101
- package/test/outbound/qfile.js +51 -53
- package/test/outbound_bounce_net_errors.js +84 -69
- package/test/outbound_bounce_rfc3464.js +235 -165
- package/test/plugins/auth/auth_base.js +420 -279
- package/test/plugins/auth/auth_vpopmaild.js +38 -39
- package/test/plugins/queue/smtp_forward.js +126 -104
- package/test/plugins/rcpt_to.host_list_base.js +85 -67
- package/test/plugins/rcpt_to.in_host_list.js +159 -112
- package/test/plugins/status.js +71 -64
- package/test/plugins/tls.js +37 -34
- package/test/plugins.js +97 -92
- package/test/rfc1869.js +19 -26
- package/test/server.js +293 -272
- package/test/smtp_client.js +180 -176
- package/test/tls_socket.js +62 -66
- package/test/transaction.js +159 -160
- package/tls_socket.js +331 -333
- package/transaction.js +129 -137
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
'use strict'
|
|
1
|
+
'use strict'
|
|
2
2
|
|
|
3
3
|
const assert = require('node:assert')
|
|
4
4
|
|
|
5
|
-
const { Address } = require('address-rfc2821')
|
|
6
|
-
const fixtures = require('haraka-test-fixtures')
|
|
5
|
+
const { Address } = require('address-rfc2821')
|
|
6
|
+
const fixtures = require('haraka-test-fixtures')
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Creates a HMailItem instance, which is passed to callback. Reports error on test param if creation fails.
|
|
@@ -13,26 +13,23 @@ const fixtures = require('haraka-test-fixtures');
|
|
|
13
13
|
* @param callback
|
|
14
14
|
*/
|
|
15
15
|
exports.newMockHMailItem = (outbound_context, done, options, callback) => {
|
|
16
|
-
const opts = options || {}
|
|
17
|
-
exports.createHMailItem(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
assert.ok(false, `Could not create HMailItem: ${err}`);
|
|
23
|
-
done()
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
if (!hmail.todo) {
|
|
27
|
-
hmail.once('ready', () => {
|
|
28
|
-
setImmediate(() => {callback(hmail);});
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
callback(hmail);
|
|
33
|
-
}
|
|
16
|
+
const opts = options || {}
|
|
17
|
+
exports.createHMailItem(outbound_context, opts, (err, hmail) => {
|
|
18
|
+
if (err) {
|
|
19
|
+
assert.ok(false, `Could not create HMailItem: ${err}`)
|
|
20
|
+
done()
|
|
21
|
+
return
|
|
34
22
|
}
|
|
35
|
-
|
|
23
|
+
if (!hmail.todo) {
|
|
24
|
+
hmail.once('ready', () => {
|
|
25
|
+
setImmediate(() => {
|
|
26
|
+
callback(hmail)
|
|
27
|
+
})
|
|
28
|
+
})
|
|
29
|
+
} else {
|
|
30
|
+
callback(hmail)
|
|
31
|
+
}
|
|
32
|
+
})
|
|
36
33
|
}
|
|
37
34
|
|
|
38
35
|
/**
|
|
@@ -43,55 +40,57 @@ exports.newMockHMailItem = (outbound_context, done, options, callback) => {
|
|
|
43
40
|
* @param callback(err, hmail)
|
|
44
41
|
*/
|
|
45
42
|
exports.createHMailItem = (outbound_context, options, callback) => {
|
|
43
|
+
const mail_from = options.mail_from || 'sender@domain'
|
|
44
|
+
const delivery_domain = options.delivery_domain || 'domain'
|
|
45
|
+
const mail_recipients = options.mail_recipients || [new Address('recipient@domain')]
|
|
46
46
|
|
|
47
|
-
const
|
|
48
|
-
const delivery_domain = options.delivery_domain || 'domain';
|
|
49
|
-
const mail_recipients = options.mail_recipients || [new Address('recipient@domain')];
|
|
50
|
-
|
|
51
|
-
const conn = fixtures.connection.createConnection();
|
|
47
|
+
const conn = fixtures.connection.createConnection()
|
|
52
48
|
conn.init_transaction()
|
|
53
|
-
conn.transaction.mail_from = new Address(mail_from)
|
|
49
|
+
conn.transaction.mail_from = new Address(mail_from)
|
|
54
50
|
|
|
55
|
-
const todo = new outbound_context.TODOItem(delivery_domain, mail_recipients, conn.transaction)
|
|
56
|
-
todo.uuid = `${todo.uuid}.1
|
|
51
|
+
const todo = new outbound_context.TODOItem(delivery_domain, mail_recipients, conn.transaction)
|
|
52
|
+
todo.uuid = `${todo.uuid}.1`
|
|
57
53
|
|
|
58
54
|
let contents = [
|
|
59
55
|
`From: ${mail_from}`,
|
|
60
|
-
`To: ${mail_recipients.join(
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
56
|
+
`To: ${mail_recipients.join(', ')}`,
|
|
57
|
+
'MIME-Version: 1.0',
|
|
58
|
+
'Content-type: text/plain; charset=us-ascii',
|
|
59
|
+
'Subject: Some subject here',
|
|
60
|
+
'',
|
|
61
|
+
'Some email body here',
|
|
62
|
+
'',
|
|
63
|
+
].join('\n')
|
|
64
|
+
let match
|
|
65
|
+
const re = /^([^\n]*\n?)/
|
|
69
66
|
while ((match = re.exec(contents))) {
|
|
70
|
-
let line = match[1]
|
|
71
|
-
line = line.replace(/\r?\n?$/, '\r\n')
|
|
72
|
-
conn.transaction.add_data(Buffer.from(line))
|
|
73
|
-
contents = contents.substr(match[1].length)
|
|
67
|
+
let line = match[1]
|
|
68
|
+
line = line.replace(/\r?\n?$/, '\r\n') // make sure it ends in \r\n
|
|
69
|
+
conn.transaction.add_data(Buffer.from(line))
|
|
70
|
+
contents = contents.substr(match[1].length)
|
|
74
71
|
if (contents.length === 0) {
|
|
75
|
-
break
|
|
72
|
+
break
|
|
76
73
|
}
|
|
77
74
|
}
|
|
78
|
-
conn.transaction.message_stream.add_line_end()
|
|
75
|
+
conn.transaction.message_stream.add_line_end()
|
|
79
76
|
|
|
80
|
-
const hmails = []
|
|
81
|
-
const ok_paths = []
|
|
82
|
-
outbound_context.exports
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
77
|
+
const hmails = []
|
|
78
|
+
const ok_paths = []
|
|
79
|
+
outbound_context.exports
|
|
80
|
+
.process_delivery(ok_paths, todo, hmails)
|
|
81
|
+
.then(() => {
|
|
82
|
+
if (hmails.length == 0) {
|
|
83
|
+
callback('No hmail producted')
|
|
84
|
+
return
|
|
85
|
+
}
|
|
86
|
+
for (const hmail of hmails) {
|
|
87
|
+
hmail.hostlist = [delivery_domain]
|
|
88
|
+
callback(null, hmail)
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
.catch((err) => {
|
|
92
|
+
callback(`process_delivery error: ${err}`)
|
|
93
|
+
})
|
|
95
94
|
}
|
|
96
95
|
|
|
97
96
|
/**
|
|
@@ -102,52 +101,57 @@ exports.createHMailItem = (outbound_context, options, callback) => {
|
|
|
102
101
|
*/
|
|
103
102
|
exports.playTestSmtpConversation = (hmail, socket, done, playbook, callback) => {
|
|
104
103
|
const testmx = {
|
|
105
|
-
bind_helo:
|
|
106
|
-
exchange:
|
|
107
|
-
}
|
|
108
|
-
hmail.try_deliver_host_on_socket(testmx, 'testhost', 'testport', socket)
|
|
104
|
+
bind_helo: 'haraka.test',
|
|
105
|
+
exchange: 'remote.testhost',
|
|
106
|
+
}
|
|
107
|
+
hmail.try_deliver_host_on_socket(testmx, 'testhost', 'testport', socket)
|
|
109
108
|
|
|
110
|
-
socket.write = line => {
|
|
109
|
+
socket.write = (line) => {
|
|
111
110
|
//console.log('MockSocket.write(' + line.replace(/\n/, '\\n').replace(/\r/, '\\r') + ')');
|
|
112
111
|
if (playbook.length == 0) {
|
|
113
|
-
assert.ok(false, 'missing next playbook entry')
|
|
112
|
+
assert.ok(false, 'missing next playbook entry')
|
|
114
113
|
done()
|
|
115
|
-
return
|
|
114
|
+
return
|
|
116
115
|
}
|
|
117
|
-
let expected
|
|
116
|
+
let expected
|
|
118
117
|
while (false != (expected = getNextEntryFromPlaybook('haraka', playbook))) {
|
|
119
118
|
if (typeof expected.test === 'function') {
|
|
120
|
-
assert.ok(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
119
|
+
assert.ok(
|
|
120
|
+
expected.test(line),
|
|
121
|
+
expected.description || `Expected that line works with func: ${expected.test}`,
|
|
122
|
+
)
|
|
123
|
+
} else {
|
|
124
|
+
assert.equal(
|
|
125
|
+
`${expected.test}\r\n`,
|
|
126
|
+
line,
|
|
127
|
+
expected.description || `Expected that line equals: ${expected.test}`,
|
|
128
|
+
)
|
|
124
129
|
}
|
|
125
130
|
if (expected.end_test === true) {
|
|
126
131
|
setTimeout(() => {
|
|
127
|
-
callback()
|
|
128
|
-
}, 0)
|
|
129
|
-
return
|
|
132
|
+
callback()
|
|
133
|
+
}, 0)
|
|
134
|
+
return
|
|
130
135
|
}
|
|
131
136
|
}
|
|
132
137
|
setTimeout(() => {
|
|
133
|
-
let nextMessageFromServer
|
|
138
|
+
let nextMessageFromServer
|
|
134
139
|
while (false != (nextMessageFromServer = getNextEntryFromPlaybook('remote', playbook))) {
|
|
135
|
-
socket.emit('line', `${nextMessageFromServer.line}\r\n`)
|
|
140
|
+
socket.emit('line', `${nextMessageFromServer.line}\r\n`)
|
|
136
141
|
}
|
|
137
|
-
}, 0)
|
|
142
|
+
}, 0)
|
|
138
143
|
}
|
|
139
144
|
|
|
140
|
-
const welcome = getNextEntryFromPlaybook('remote', playbook)
|
|
141
|
-
socket.emit('line', welcome.line)
|
|
145
|
+
const welcome = getNextEntryFromPlaybook('remote', playbook)
|
|
146
|
+
socket.emit('line', welcome.line)
|
|
142
147
|
}
|
|
143
148
|
|
|
144
|
-
function getNextEntryFromPlaybook
|
|
149
|
+
function getNextEntryFromPlaybook(ofType, playbook) {
|
|
145
150
|
if (playbook.length == 0) {
|
|
146
|
-
return false
|
|
151
|
+
return false
|
|
147
152
|
}
|
|
148
153
|
if (playbook[0].from == ofType) {
|
|
149
|
-
return playbook.shift()
|
|
154
|
+
return playbook.shift()
|
|
150
155
|
}
|
|
151
|
-
return false
|
|
156
|
+
return false
|
|
152
157
|
}
|
|
153
|
-
|
package/test/host_pool.js
CHANGED
|
@@ -1,58 +1,56 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict'
|
|
2
2
|
|
|
3
3
|
const assert = require('node:assert')
|
|
4
4
|
|
|
5
|
-
const HostPool = require('../host_pool')
|
|
5
|
+
const HostPool = require('../host_pool')
|
|
6
6
|
|
|
7
7
|
describe('HostPool', () => {
|
|
8
|
-
it(
|
|
8
|
+
it('get a host', (done) => {
|
|
9
|
+
const pool = new HostPool('1.1.1.1:1111, 2.2.2.2:2222')
|
|
10
|
+
const host = pool.get_host()
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
assert.ok( /\d\.\d\.\d\.\d/.test(host.host), `'${host.host}' looks like a IP`);
|
|
14
|
-
assert.ok( /\d\d\d\d/.test(host.port), `'${host.port}' looks like a port`);
|
|
12
|
+
assert.ok(/\d\.\d\.\d\.\d/.test(host.host), `'${host.host}' looks like a IP`)
|
|
13
|
+
assert.ok(/\d\d\d\d/.test(host.port), `'${host.port}' looks like a port`)
|
|
15
14
|
done()
|
|
16
15
|
})
|
|
17
16
|
|
|
18
|
-
it(
|
|
19
|
-
|
|
20
|
-
const pool = new HostPool('1.1.1.1:1111, 2.2.2.2:2222');
|
|
17
|
+
it('uses all the list', (done) => {
|
|
18
|
+
const pool = new HostPool('1.1.1.1:1111, 2.2.2.2:2222')
|
|
21
19
|
|
|
22
|
-
const host1 = pool.get_host()
|
|
23
|
-
const host2 = pool.get_host()
|
|
24
|
-
const host3 = pool.get_host()
|
|
20
|
+
const host1 = pool.get_host()
|
|
21
|
+
const host2 = pool.get_host()
|
|
22
|
+
const host3 = pool.get_host()
|
|
25
23
|
|
|
26
|
-
assert.notEqual(host1.host, host2.host)
|
|
27
|
-
assert.notEqual(host3.host, host2.host)
|
|
28
|
-
assert.equal(host3.host, host1.host)
|
|
24
|
+
assert.notEqual(host1.host, host2.host)
|
|
25
|
+
assert.notEqual(host3.host, host2.host)
|
|
26
|
+
assert.equal(host3.host, host1.host)
|
|
29
27
|
done()
|
|
30
28
|
})
|
|
31
29
|
|
|
32
|
-
it(
|
|
33
|
-
const pool = new HostPool('1.1.1.1, 2.2.2.2')
|
|
30
|
+
it('default port 25', (done) => {
|
|
31
|
+
const pool = new HostPool('1.1.1.1, 2.2.2.2')
|
|
34
32
|
|
|
35
|
-
const host1 = pool.get_host()
|
|
36
|
-
const host2 = pool.get_host()
|
|
33
|
+
const host1 = pool.get_host()
|
|
34
|
+
const host2 = pool.get_host()
|
|
37
35
|
|
|
38
|
-
assert.equal(host1.port, 25, `is port 25: ${host1.port}`)
|
|
39
|
-
assert.equal(host2.port, 25, `is port 25: ${host2.port}`)
|
|
36
|
+
assert.equal(host1.port, 25, `is port 25: ${host1.port}`)
|
|
37
|
+
assert.equal(host2.port, 25, `is port 25: ${host2.port}`)
|
|
40
38
|
done()
|
|
41
39
|
})
|
|
42
40
|
|
|
43
|
-
it(
|
|
44
|
-
const pool = new HostPool('1.1.1.1:1111, 2.2.2.2:2222')
|
|
41
|
+
it('dead host', (done) => {
|
|
42
|
+
const pool = new HostPool('1.1.1.1:1111, 2.2.2.2:2222')
|
|
45
43
|
|
|
46
|
-
pool.failed('1.1.1.1', '1111')
|
|
44
|
+
pool.failed('1.1.1.1', '1111')
|
|
47
45
|
|
|
48
|
-
let host
|
|
46
|
+
let host
|
|
49
47
|
|
|
50
|
-
host = pool.get_host()
|
|
51
|
-
assert.equal(host.host, '2.2.2.2', 'dead host is not returned')
|
|
52
|
-
host = pool.get_host()
|
|
53
|
-
assert.equal(host.host, '2.2.2.2', 'dead host is not returned')
|
|
54
|
-
host = pool.get_host()
|
|
55
|
-
assert.equal(host.host, '2.2.2.2', 'dead host is not returned')
|
|
48
|
+
host = pool.get_host()
|
|
49
|
+
assert.equal(host.host, '2.2.2.2', 'dead host is not returned')
|
|
50
|
+
host = pool.get_host()
|
|
51
|
+
assert.equal(host.host, '2.2.2.2', 'dead host is not returned')
|
|
52
|
+
host = pool.get_host()
|
|
53
|
+
assert.equal(host.host, '2.2.2.2', 'dead host is not returned')
|
|
56
54
|
done()
|
|
57
55
|
})
|
|
58
56
|
|
|
@@ -60,105 +58,105 @@ describe('HostPool', () => {
|
|
|
60
58
|
// accidentally DOS'ing ourselves if there's a transient but widespread
|
|
61
59
|
// network outage
|
|
62
60
|
it("they're all dead", (done) => {
|
|
61
|
+
let host1
|
|
62
|
+
let host2
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
let host2;
|
|
66
|
-
|
|
67
|
-
const pool = new HostPool('1.1.1.1:1111, 2.2.2.2:2222');
|
|
64
|
+
const pool = new HostPool('1.1.1.1:1111, 2.2.2.2:2222')
|
|
68
65
|
|
|
69
|
-
host1 = pool.get_host()
|
|
66
|
+
host1 = pool.get_host()
|
|
70
67
|
|
|
71
|
-
pool.failed('1.1.1.1', '1111')
|
|
72
|
-
pool.failed('2.2.2.2', '2222')
|
|
68
|
+
pool.failed('1.1.1.1', '1111')
|
|
69
|
+
pool.failed('2.2.2.2', '2222')
|
|
73
70
|
|
|
74
|
-
host2 = pool.get_host()
|
|
75
|
-
assert.ok
|
|
76
|
-
assert.notEqual(host1.host, host2.host,
|
|
71
|
+
host2 = pool.get_host()
|
|
72
|
+
assert.ok(host2, "if they're all dead, try one anyway")
|
|
73
|
+
assert.notEqual(host1.host, host2.host, 'rotation continues')
|
|
77
74
|
|
|
78
|
-
host1 = pool.get_host()
|
|
79
|
-
assert.ok
|
|
80
|
-
assert.notEqual(host1.host, host2.host,
|
|
75
|
+
host1 = pool.get_host()
|
|
76
|
+
assert.ok(host1, "if they're all dead, try one anyway")
|
|
77
|
+
assert.notEqual(host1.host, host2.host, 'rotation continues')
|
|
81
78
|
|
|
82
|
-
host2 = pool.get_host()
|
|
83
|
-
assert.ok
|
|
84
|
-
assert.notEqual(host1.host, host2.host,
|
|
79
|
+
host2 = pool.get_host()
|
|
80
|
+
assert.ok(host2, "if they're all dead, try one anyway")
|
|
81
|
+
assert.notEqual(host1.host, host2.host, 'rotation continues')
|
|
85
82
|
done()
|
|
86
83
|
})
|
|
87
84
|
|
|
88
85
|
// after .01 secs the timer to retry the dead host will fire, and then
|
|
89
86
|
// we connect using this mock socket, whose "connect" always succeeds
|
|
90
87
|
// so the code brings the dead host back to life
|
|
91
|
-
it(
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const MockSocket = function MockSocket (pool) {
|
|
95
|
-
|
|
88
|
+
it('host dead checking timer', (done) => {
|
|
89
|
+
let num_reqs = 0
|
|
90
|
+
const MockSocket = function MockSocket(pool) {
|
|
96
91
|
// these are the methods called from probe_dead_host
|
|
97
92
|
|
|
98
93
|
// setTimeout on the socket
|
|
99
|
-
this.pretendTimeout = () => {}
|
|
94
|
+
this.pretendTimeout = () => {}
|
|
100
95
|
this.setTimeout = (ms, cb) => {
|
|
101
|
-
this.pretendTimeout = cb
|
|
102
|
-
}
|
|
96
|
+
this.pretendTimeout = cb
|
|
97
|
+
}
|
|
103
98
|
// handle socket.on('error', ....
|
|
104
|
-
this.listeners = {}
|
|
99
|
+
this.listeners = {}
|
|
105
100
|
this.on = (eventname, cb) => {
|
|
106
|
-
this.listeners[eventname] = cb
|
|
107
|
-
}
|
|
108
|
-
this.emit = eventname => {
|
|
109
|
-
this.listeners[eventname]()
|
|
110
|
-
}
|
|
101
|
+
this.listeners[eventname] = cb
|
|
102
|
+
}
|
|
103
|
+
this.emit = (eventname) => {
|
|
104
|
+
this.listeners[eventname]()
|
|
105
|
+
}
|
|
111
106
|
// handle socket.connect(...
|
|
112
|
-
this.connected = () => {}
|
|
107
|
+
this.connected = () => {}
|
|
113
108
|
this.connect = (port, host, cb) => {
|
|
114
109
|
switch (++num_reqs) {
|
|
115
110
|
case 1:
|
|
116
111
|
// the first time through we pretend it timed out
|
|
117
|
-
this.pretendTimeout()
|
|
118
|
-
break
|
|
112
|
+
this.pretendTimeout()
|
|
113
|
+
break
|
|
119
114
|
case 2:
|
|
120
115
|
// the second time through, pretend socket error
|
|
121
|
-
this.emit('error')
|
|
122
|
-
break
|
|
116
|
+
this.emit('error')
|
|
117
|
+
break
|
|
123
118
|
case 3:
|
|
124
119
|
// the third time around, the socket connected
|
|
125
|
-
cb()
|
|
126
|
-
break
|
|
120
|
+
cb()
|
|
121
|
+
break
|
|
127
122
|
default:
|
|
128
123
|
// failsafe
|
|
129
|
-
console.log(`num_reqs hit ${num_reqs}, wtf?`)
|
|
130
|
-
process.exit(1)
|
|
124
|
+
console.log(`num_reqs hit ${num_reqs}, wtf?`)
|
|
125
|
+
process.exit(1)
|
|
131
126
|
}
|
|
132
|
-
}
|
|
133
|
-
this.destroy = () => {}
|
|
134
|
-
}
|
|
127
|
+
}
|
|
128
|
+
this.destroy = () => {}
|
|
129
|
+
}
|
|
135
130
|
|
|
136
|
-
const retry_secs = 0.001
|
|
137
|
-
const pool = new HostPool('1.1.1.1:1111, 2.2.2.2:2222', retry_secs)
|
|
131
|
+
const retry_secs = 0.001 // 1ms
|
|
132
|
+
const pool = new HostPool('1.1.1.1:1111, 2.2.2.2:2222', retry_secs)
|
|
138
133
|
|
|
139
134
|
// override the pool's get_socket method to return our mock
|
|
140
|
-
pool.get_socket = () => new MockSocket
|
|
135
|
+
pool.get_socket = () => new MockSocket(pool)
|
|
141
136
|
|
|
142
137
|
// mark the host as failed and start up the retry timers
|
|
143
|
-
pool.failed('1.1.1.1', '1111')
|
|
138
|
+
pool.failed('1.1.1.1', '1111')
|
|
144
139
|
|
|
145
|
-
assert.ok(pool.dead_hosts[
|
|
140
|
+
assert.ok(pool.dead_hosts['1.1.1.1:1111'], 'yes it was marked dead')
|
|
146
141
|
|
|
147
142
|
// probe_dead_host() will hit two failures and one success (based on
|
|
148
143
|
// num_reqs above). So we wait at least 10s for that to happen:
|
|
149
144
|
const timer = setTimeout(() => {
|
|
150
|
-
clearInterval(interval)
|
|
151
|
-
assert.ok(false, 'probe_dead_host failed')
|
|
145
|
+
clearInterval(interval)
|
|
146
|
+
assert.ok(false, 'probe_dead_host failed')
|
|
152
147
|
done()
|
|
153
|
-
}, 10 * 1000)
|
|
154
|
-
|
|
155
|
-
const interval = setInterval(
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
148
|
+
}, 10 * 1000)
|
|
149
|
+
|
|
150
|
+
const interval = setInterval(
|
|
151
|
+
() => {
|
|
152
|
+
if (!pool.dead_hosts['1.1.1.1:1111']) {
|
|
153
|
+
clearTimeout(timer)
|
|
154
|
+
clearInterval(interval)
|
|
155
|
+
assert.ok(true, 'timer un-deaded it')
|
|
156
|
+
done()
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
retry_secs * 1000 * 3,
|
|
160
|
+
)
|
|
163
161
|
})
|
|
164
162
|
})
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict'
|
|
2
2
|
|
|
3
|
-
exports.check_the_base = () =>
|
|
3
|
+
exports.check_the_base = () => 'base'
|