1// Copyright Joyent, Inc. and other Node contributors. 2// 3// Permission is hereby granted, free of charge, to any person obtaining a 4// copy of this software and associated documentation files (the 5// "Software"), to deal in the Software without restriction, including 6// without limitation the rights to use, copy, modify, merge, publish, 7// distribute, sublicense, and/or sell copies of the Software, and to permit 8// persons to whom the Software is furnished to do so, subject to the 9// following conditions: 10// 11// The above copyright notice and this permission notice shall be included 12// in all copies or substantial portions of the Software. 13// 14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20// USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22'use strict'; 23const common = require('../common'); 24const assert = require('assert'); 25const net = require('net'); 26 27function pingPongTest(port, host) { 28 const N = 1000; 29 let count = 0; 30 let sentPongs = 0; 31 let sent_final_ping = false; 32 33 const server = net.createServer( 34 { allowHalfOpen: true }, 35 common.mustCall(onSocket) 36 ); 37 38 function onSocket(socket) { 39 assert.strictEqual(socket.server, server); 40 assert.strictEqual( 41 server, 42 server.getConnections(common.mustCall(function(err, connections) { 43 assert.ifError(err); 44 assert.strictEqual(connections, 1); 45 })) 46 ); 47 48 socket.setNoDelay(); 49 socket.timeout = 0; 50 51 socket.setEncoding('utf8'); 52 socket.on('data', common.mustCall(function(data) { 53 // Since we never queue data (we're always waiting for the PING 54 // before sending a pong) the writeQueueSize should always be less 55 // than one message. 56 assert.ok(socket.bufferSize >= 0 && socket.bufferSize <= 4); 57 58 assert.strictEqual(socket.writable, true); 59 assert.strictEqual(socket.readable, true); 60 assert.ok(count <= N); 61 assert.strictEqual(data, 'PING'); 62 63 socket.write('PONG', common.mustCall(function() { 64 sentPongs++; 65 })); 66 }, N + 1)); 67 68 socket.on('end', common.mustCall(function() { 69 assert.strictEqual(socket.allowHalfOpen, true); 70 assert.strictEqual(socket.writable, true); // Because allowHalfOpen 71 assert.strictEqual(socket.readable, false); 72 socket.end(); 73 })); 74 75 socket.on('error', common.mustNotCall()); 76 77 socket.on('close', common.mustCall(function() { 78 assert.strictEqual(socket.writable, false); 79 assert.strictEqual(socket.readable, false); 80 socket.server.close(); 81 })); 82 } 83 84 85 server.listen(port, host, common.mustCall(function() { 86 if (this.address().port) 87 port = this.address().port; 88 89 const client = net.createConnection(port, host); 90 91 client.setEncoding('ascii'); 92 client.on('connect', common.mustCall(function() { 93 assert.strictEqual(client.readable, true); 94 assert.strictEqual(client.writable, true); 95 client.write('PING'); 96 })); 97 98 client.on('data', common.mustCall(function(data) { 99 assert.strictEqual(data, 'PONG'); 100 count += 1; 101 102 if (sent_final_ping) { 103 assert.strictEqual(client.writable, false); 104 assert.strictEqual(client.readable, true); 105 return; 106 } 107 assert.strictEqual(client.writable, true); 108 assert.strictEqual(client.readable, true); 109 110 if (count < N) { 111 client.write('PING'); 112 } else { 113 sent_final_ping = true; 114 client.write('PING'); 115 client.end(); 116 } 117 }, N + 1)); 118 119 client.on('close', common.mustCall(function() { 120 assert.strictEqual(count, N + 1); 121 assert.strictEqual(sentPongs, N + 1); 122 assert.strictEqual(sent_final_ping, true); 123 })); 124 125 client.on('error', common.mustNotCall()); 126 })); 127} 128 129/* All are run at once, so run on different ports */ 130const tmpdir = require('../common/tmpdir'); 131tmpdir.refresh(); 132pingPongTest(common.PIPE); 133pingPongTest(0); 134pingPongTest(0, 'localhost'); 135if (common.hasIPv6) 136 pingPongTest(0, '::1'); 137