diff --git a/lib/servers.js b/lib/servers.js index 280e716..e7f4d1f 100644 --- a/lib/servers.js +++ b/lib/servers.js @@ -1,10 +1,10 @@ 'use strict'; var serversMap = module.exports._serversMap = {}; +var dgramMap = module.exports._dgramMap = {}; +var PromiseA = require('bluebird'); module.exports.addTcpListener = function (port, handler) { - var PromiseA = require('bluebird'); - return new PromiseA(function (resolve, reject) { var stat = serversMap[port]; @@ -34,7 +34,7 @@ module.exports.addTcpListener = function (port, handler) { stat = serversMap[port] = { server: server , handler: handler - , _closing: false + , _closing: null }; // Add .destroy so we can close all open connections. Better if added before listen @@ -69,8 +69,6 @@ module.exports.addTcpListener = function (port, handler) { }); }; module.exports.closeTcpListener = function (port) { - var PromiseA = require('bluebird'); - return new PromiseA(function (resolve) { var stat = serversMap[port]; if (!stat) { @@ -101,10 +99,79 @@ module.exports.destroyTcpListener = function (port) { stat = null; }; +module.exports.addUdpListener = function (port, handler) { + return new PromiseA(function (resolve, reject) { + var stat = dgramMap[port]; + + if (stat) { + // we'll replace the current listener + stat.handler = handler; + resolve(); + return; + } + + var dgram = require('dgram'); + var server = dgram.createSocket('udp4'); + var resolved = false; + + stat = dgramMap[port] = { + server: server + , handler: handler + }; + + server.on('message', function (msg, rinfo) { + msg._size = rinfo.size; + msg._remoteFamily = rinfo.family; + msg._remoteAddress = rinfo.address; + msg._remotePort = rinfo.port; + msg._port = port; + stat.handler(msg); + }); + + server.on('error', function (err) { + if (!resolved) { + delete dgramMap[port]; + reject(err); + } + else if (stat.handler.onError) { + stat.handler.onError(err); + } + else { + throw err; + } + }); + + server.on('close', function () { + delete dgramMap[port]; + }); + + server.bind(port, function () { + resolved = true; + resolve(); + }); + }); +}; +module.exports.closeUdpListener = function (port) { + var stat = dgramMap[port]; + if (!stat) { + return PromiseA.resolve(); + } + + return new PromiseA(function (resolve) { + stat.server.once('close', resolve); + stat.server.close(); + }); +}; + + module.exports.listeners = { tcp: { add: module.exports.addTcpListener , close: module.exports.closeTcpListener , destroy: module.exports.destroyTcpListener } +, udp: { + add: module.exports.addUdpListener + , close: module.exports.closeUdpListener + } };