| // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Tests for multicast UDP socket. |
| function testMulticast() { |
| function randomHexString(count) { |
| var result = ''; |
| for (var i = 0; i < count; i++) { |
| result += (Math.random() * 16 >> 0).toString(16); |
| } |
| return result; |
| } |
| |
| var kMulticastAddress = "237.132.100.133"; |
| var kTestMessageLength = 128; |
| var kTestMessage = randomHexString(128); |
| var kPort = 11103; |
| |
| function arrayBufferToString(arrayBuffer) { |
| // UTF-16LE |
| return String.fromCharCode.apply(String, new Uint16Array(arrayBuffer)); |
| } |
| |
| function stringToArrayBuffer(string) { |
| // UTF-16LE |
| var buf = new ArrayBuffer(string.length * 2); |
| var bufView = new Uint16Array(buf); |
| for (var i = 0, strLen = string.length; i < strLen; i++) { |
| bufView[i] = string.charCodeAt(i); |
| } |
| return buf; |
| } |
| |
| function waitForMessage(socketId, callback) { |
| var cancelled = false; |
| var relayCanceller = null; |
| socket.recvFrom(socketId, 1024, function (result) { |
| if (cancelled) |
| return; |
| |
| if (result.resultCode == kTestMessageLength * 2 && |
| kTestMessage === arrayBufferToString(result.data)) { |
| callback(cancelled); |
| } else { |
| // Restart waiting. |
| relayCanceller = waitForMessage(socketId, callback); |
| } |
| }); |
| return function canceller() { |
| if (relayCanceller) { |
| relayCanceller(); |
| } else { |
| cancelled = true; |
| callback(true); |
| } |
| }; |
| } |
| |
| function testMulticastSettings() { |
| socket.create('udp', {}, function (socketInfo) { |
| var socket_id; |
| if (socketInfo) { |
| socket_id = socketInfo.socketId; |
| socket.setMulticastTimeToLive(socket_id, 0, function (result) { |
| chrome.test.assertEq(0, result, |
| "Error setting multicast time to live."); |
| socket.setMulticastTimeToLive(socket_id, -3, function (result) { |
| chrome.test.assertEq(-4, result, |
| "Error setting multicast time to live."); |
| socket.setMulticastLoopbackMode(socket_id, false, |
| function (result) { |
| chrome.test.assertEq(0, result, |
| "Error setting multicast loop back mode."); |
| socket.setMulticastLoopbackMode(socket_id, true, |
| function (result) { |
| chrome.test.assertEq(0, result, |
| "Error setting multicast loop back mode."); |
| socket.destroy(socket_id); |
| testMulticastRecv(); |
| }); |
| }); |
| }); |
| }); |
| } else { |
| chrome.test.fail("Cannot create server udp socket"); |
| } |
| }); |
| } |
| |
| function testSendMessage(message, address) { |
| // Send the UDP message to the address with multicast ttl = 0. |
| address = address || kMulticastAddress; |
| socket.create('udp', {}, function (socketInfo) { |
| var clientSocketId; |
| if (socketInfo) { |
| clientSocketId = socketInfo.socketId; |
| chrome.test.assertTrue(clientSocketId > 0, |
| "Cannot create client udp socket."); |
| socket.setMulticastTimeToLive(clientSocketId, 0, function (result) { |
| chrome.test.assertEq(0, result, |
| "Cannot create client udp socket."); |
| socket.connect(clientSocketId, address, kPort, function (result) { |
| chrome.test.assertEq(0, result, |
| "Cannot connect to localhost."); |
| socket.write(clientSocketId, stringToArrayBuffer(kTestMessage), |
| function (result) { |
| chrome.test.assertTrue(result.bytesWritten >= 0, |
| "Send to failed. " + JSON.stringify(result)); |
| socket.destroy(clientSocketId); |
| }); |
| }); |
| }); |
| } else { |
| chrome.test.fail("Cannot create client udp socket"); |
| } |
| }); |
| } |
| |
| function recvBeforeAddMembership(serverSocketId) { |
| var recvTimeout; |
| var canceller = waitForMessage(serverSocketId, function (cancelled) { |
| clearTimeout(recvTimeout); |
| if (cancelled) { |
| recvWithMembership(serverSocketId); |
| } else { |
| chrome.test.fail("Received message before joining the group"); |
| } |
| }); |
| testSendMessage(kTestMessage); // Meant to be lost. |
| recvTimeout = setTimeout(function () { |
| canceller(); |
| testSendMessage(kTestMessage, "127.0.0.1", kPort); |
| }, 2000); |
| } |
| |
| function recvWithMembership(serverSocketId) { |
| // Join group. |
| socket.joinGroup(serverSocketId, kMulticastAddress, function (result) { |
| chrome.test.assertEq(0, result, "Join group failed."); |
| var recvTimeout; |
| var canceller = waitForMessage(serverSocketId, function (cancelled) { |
| clearTimeout(recvTimeout); |
| if (!cancelled) { |
| recvWithoutMembership(serverSocketId); |
| } else { |
| chrome.test.fail("Faild to receive message after joining the group"); |
| } |
| }); |
| testSendMessage(kTestMessage); |
| recvTimeout = setTimeout(function () { |
| canceller(); |
| socket.destroy(serverSocketId); |
| chrome.test.fail("Cannot receive from multicast group."); |
| }, 2000); |
| }); |
| } |
| |
| function recvWithoutMembership(serverSocketId) { |
| socket.leaveGroup(serverSocketId, kMulticastAddress, function (result) { |
| chrome.test.assertEq(0, result, "leave group failed."); |
| var recvTimeout; |
| var canceller = waitForMessage(serverSocketId, function (cancelled) { |
| clearTimeout(recvTimeout); |
| if (cancelled) { |
| socket.destroy(serverSocketId); |
| chrome.test.succeed(); |
| } else { |
| chrome.test.fail("Received message after leaving the group"); |
| socket.destroy(serverSocketId); |
| } |
| }); |
| testSendMessage(request); |
| recvTimeout = setTimeout(function () { |
| canceller(); |
| socket.destroy(serverSocketId); |
| chrome.test.succeed(); |
| }, 2000); |
| }); |
| } |
| |
| function testMulticastRecv() { |
| socket.create('udp', {}, function (socketInfo) { |
| var serverSocketId; |
| if (socketInfo) { |
| serverSocketId = socketInfo.socketId; |
| socket.bind(serverSocketId, "0.0.0.0", kPort, function (result) { |
| chrome.test.assertEq(0, result, "Bind failed."); |
| recvBeforeAddMembership(serverSocketId); |
| }); |
| } else { |
| chrome.test.fail("Cannot create server udp socket"); |
| } |
| }); |
| } |
| |
| testMulticastSettings(); |
| } |