UNPKG

3.32 kBJavaScriptView Raw
1/*jshint node:true, laxcomma:true */
2
3var util = require('util')
4 , dgram = require('dgram')
5 , logger = require('../lib/logger')
6 , Pool = require('generic-pool').Pool
7 , net = require('net');
8
9
10var l;
11var debug;
12var instance;
13
14function logerror(err) {
15 if(err && debug) {
16 l.log(err);
17 }
18}
19
20
21
22function UDPRepeaterBackend(startupTime, config, emitter) {
23 var self = this;
24 this.config = config.repeater || [];
25 this.sock = (config.repeaterProtocol == 'udp6') ?
26 dgram.createSocket('udp6') :
27 dgram.createSocket('udp4');
28
29 // Attach DNS error handler
30 this.sock.on('error', function (err) {
31 if (debug) {
32 l.log('Repeater error: ' + err);
33 }
34 });
35
36 // attach
37 emitter.on('packet', function(packet, rinfo) { self.process(packet, rinfo); });
38}
39
40
41UDPRepeaterBackend.prototype.process = function(packet, rinfo) {
42 var self = this;
43 var hosts = self.config;
44 for(var i=0; i<hosts.length; i++) {
45 self.sock.send(packet,0,packet.length,hosts[i].port,hosts[i].host,logerror);
46 }
47};
48
49UDPRepeaterBackend.prototype.stop = function(cb) {
50 this.sock.close();
51 cb();
52};
53
54
55
56var TCPRepeaterBackend = function(startupTime, config, emitter) {
57 this.config = config;
58 this.pools = [];
59
60 var targets = this.config.repeater || [];
61 for(var i = 0; i < targets.length; i++) {
62 this.pools.push(this.createPool(targets[i]));
63 }
64
65 var self = this;
66 emitter.on('packet', function(packet, rinfo) { self.process(packet, rinfo); });
67};
68
69
70TCPRepeaterBackend.prototype.createPool = function(server) {
71 return Pool({
72 name: server.host + ':' + server.port,
73
74 create: function(cb) {
75 var client = net.connect(server.port, server.host);
76
77 function connectError(err) { cb(err, null); }
78
79 client.on('connect', function() {
80 client.removeListener('error', connectError);
81 cb(null, client);
82 });
83
84 client.on('error', connectError);
85 },
86
87 destroy: function(client) {
88 client.end();
89 },
90
91 max: 5
92 });
93};
94
95TCPRepeaterBackend.prototype.process = function(packet, rinfo) {
96 function send(buf, pool) {
97 pool.acquire(function(err, client) {
98 if(err) {
99 logerror(err);
100 } else {
101 client.write(buf, function() {
102 pool.release(client);
103 });
104 }
105 });
106 }
107
108 for(var i = 0; i < this.pools.length; i++) {
109 send(new Buffer(packet.toString() + "\n"), this.pools[i]);
110 }
111};
112
113
114TCPRepeaterBackend.prototype.stop = function(cb) {
115 var self = this;
116 function drain_pool(i) {
117 if(i == self.pools.length) {
118 cb();
119 return;
120 }
121
122 self.pools[i].drain(function() {
123 self.pools[i].destroyAllNow(function() {
124 drain_pool(i + 1);
125 });
126 });
127 }
128
129 drain_pool(0);
130};
131
132
133exports.init = function(startupTime, config, emitter, logger) {
134 debug = config.debug;
135 l = logger;
136
137 var proto = config.repeaterProtocol;
138 if(proto == 'tcp') {
139 instance = new TCPRepeaterBackend(startupTime, config, emitter);
140 } else {
141 instance = new UDPRepeaterBackend(startupTime, config, emitter);
142 }
143
144 return true;
145};
146
147
148exports.stop = function(cb) {
149 if(instance) {
150 instance.stop(cb);
151 instance = null;
152 }
153};