Source: node-strategy.js

/**
 * @file NodeStrategy
 * @copyright Monohm, Inc. 2014
 */

monohm.provide ("sensible.node.Strategy");

/**
 * Implementation of Strategy for the Node platform.
 *
 * @class sensible.node.Strategy
 */
 
sensible.node.Strategy = function ()
{
	sensible.Strategy.call (this);
}
monohm.inherits (sensible.node.Strategy, sensible.Strategy);

/**
 * Subscribe the UDP socket to a multicast address.
 *
 * @param {string} inMulticastAddress - multicast address to join, eg 224.0.0.251 for MDNS
 * @param {function} inCallback - function to call on completion
 */

sensible.node.Strategy.prototype.subscribe = function (inMulticastAddress, inCallback)
{
	
	if (inCallback)
	{
		inCallback ();
	}
}

/**
 * Open the MDNS socket and join the multicast group.
 * Note only one UDP socket per strategy instance.
 *
 * @param {function} inCallback - function to call on completion
 */
sensible.node.Strategy.prototype.open = function (inCallback)
{
	// console.log ("sensible.node.Strategy.open()");
	
	this.socket = dgram.createSocket ("udp4");

	var	self = this;
	
	// note that later nodes require the address parameter
	this.socket.bind
	(
		5353,
		"0.0.0.0",
		function (inError)
		{
			if (!inError)
			{
				self.socket.subscribe ("224.0.0.251");
			}

			inCallback (inError);
		}
	);
}

/**
 * Close the UDP socket and bind to the specified port.
 *
 * @param {integer} inPort - port to which to bind, eg 5353 for MDNS
 * @param {function} inCallback - function to call on completion
 */
sensible.node.Strategy.prototype.close = function ()
{
	this.socket.close ();
}

/**
 * Return the host name of the machine.
 *
 * @returns {string} host name
 */
sensible.node.Strategy.prototype.getHostName = function (inCallback)
{
	inCallback (os.hostname ());
}

/**
 * Return the IP address of the machine.
 *
 * @returns {string} IP address
 */
sensible.node.Strategy.prototype.getIPAddress = function (inCallback)
{
	var	address = null;
	
	var	interfaces = os.networkInterfaces ();
	
	for (var name in interfaces)
	{
		var	addresses = interfaces [name];
		
		for (var i = 0; i < addresses.length; i++)
		{
			var	address = addresses [i];
			
			if (! address.internal)
			{
				if (address.family.toLowerCase () == "ipv4")
				{
					// should probably check for dups here, but how would we?
					address = address.address;

					break;
				}
			}
		}
		
		if (address && address.length)
		{
			break;
		}
	}

	if (address == null || address.length == 0)
	{
		address = "127.0.0.1";
	}

	inCallback (address);
}

/**
 * Listen for packets on the UDP socket.
 *
 * @param {function} inCallback - function to call on reception
 */
sensible.node.Strategy.prototype.listen = function (inCallback)
{
	this.socket.on
	(
		"message",
		function (inMessage, inRemoteInfo)
		{
			// convert to arraybuffer for the rest of the world
			var	buffer = new ArrayBuffer (inMessage.length);
			var	view = new Uint8Array (buffer);
			
			for (var i = 0; i < inMessage.length; i++)
			{
				view [i] = inMessage [i];
			}
	
			inCallback (buffer, inRemoteInfo.address, inRemoteInfo.port);
		}
	);
}

/**
 * Send a packet on the UDP socket.
 *
 * @param {ArrayBuffer} inPacket - packet
 * @param {string} inRemoteAddress - remote address
 * @param {port} inRemotePort - remote port
 */
sensible.node.Strategy.prototype.send = function (inPacket, inRemoteAddress, inRemotePort)
{
	var	view = new Uint8Array (inPacket);

	var	buffer = new Buffer (inPacket.byteLength);
	
	for (var i = 0; i < inPacket.byteLength; i++)
	{
		buffer.writeUInt8 (view [i], i);
	}

	this.socket.send
	(
		buffer, 0, buffer.length, inRemotePort, inRemoteAddress,
		function (inError, inBytes)
		{
			if (inError)
			{
				console.log ("error sending request");
				console.log (inError);
			}
		}
	);
}