michael@0: const Cc = Components.classes; michael@0: const Ci = Components.interfaces; michael@0: const Cr = Components.results; michael@0: const Cu = Components.utils; michael@0: const CC = Components.Constructor; michael@0: michael@0: Cu.import("resource://gre/modules/Services.jsm"); michael@0: michael@0: const ServerSocket = CC("@mozilla.org/network/server-socket;1", michael@0: "nsIServerSocket", michael@0: "init"), michael@0: InputStreamPump = CC("@mozilla.org/network/input-stream-pump;1", michael@0: "nsIInputStreamPump", michael@0: "init"), michael@0: BinaryInputStream = CC("@mozilla.org/binaryinputstream;1", michael@0: "nsIBinaryInputStream", michael@0: "setInputStream"), michael@0: BinaryOutputStream = CC("@mozilla.org/binaryoutputstream;1", michael@0: "nsIBinaryOutputStream", michael@0: "setOutputStream"), michael@0: TCPSocket = new (CC("@mozilla.org/tcp-socket;1", michael@0: "nsIDOMTCPSocket"))(); michael@0: michael@0: var server = null, sock = null; michael@0: michael@0: /** michael@0: * Spin up a listening socket and associate at most one live, accepted socket michael@0: * with ourselves. michael@0: */ michael@0: function TestServer() { michael@0: this.listener = ServerSocket(-1, true, -1); michael@0: do_print('server: listening on', this.listener.port); michael@0: this.listener.asyncListen(this); michael@0: michael@0: this.binaryInput = null; michael@0: this.input = null; michael@0: this.binaryOutput = null; michael@0: this.output = null; michael@0: michael@0: this.onaccept = null; michael@0: this.ondata = null; michael@0: this.onclose = null; michael@0: } michael@0: michael@0: TestServer.prototype = { michael@0: onSocketAccepted: function(socket, trans) { michael@0: if (this.input) michael@0: do_throw("More than one live connection!?"); michael@0: michael@0: do_print('server: got client connection'); michael@0: this.input = trans.openInputStream(0, 0, 0); michael@0: this.binaryInput = new BinaryInputStream(this.input); michael@0: this.output = trans.openOutputStream(0, 0, 0); michael@0: this.binaryOutput = new BinaryOutputStream(this.output); michael@0: michael@0: new InputStreamPump(this.input, -1, -1, 0, 0, false).asyncRead(this, null); michael@0: michael@0: if (this.onaccept) michael@0: this.onaccept(); michael@0: else michael@0: do_throw("Received unexpected connection!"); michael@0: }, michael@0: michael@0: onStopListening: function(socket) { michael@0: }, michael@0: michael@0: onDataAvailable: function(request, context, inputStream, offset, count) { michael@0: var readData = this.binaryInput.readByteArray(count); michael@0: if (this.ondata) { michael@0: try { michael@0: this.ondata(readData); michael@0: } catch(ex) { michael@0: // re-throw if this is from do_throw michael@0: if (ex === Cr.NS_ERROR_ABORT) michael@0: throw ex; michael@0: // log if there was a test problem michael@0: do_print('Caught exception: ' + ex + '\n' + ex.stack); michael@0: do_throw('test is broken; bad ondata handler; see above'); michael@0: } michael@0: } else { michael@0: do_throw('Received ' + count + ' bytes of unexpected data!'); michael@0: } michael@0: }, michael@0: michael@0: onStartRequest: function(request, context) { michael@0: }, michael@0: michael@0: onStopRequest: function(request, context, status) { michael@0: if (this.onclose) michael@0: this.onclose(); michael@0: else michael@0: do_throw("Received unexpected close!"); michael@0: }, michael@0: michael@0: close: function() { michael@0: this.binaryInput.close(); michael@0: this.binaryOutput.close(); michael@0: }, michael@0: michael@0: /** michael@0: * Forget about the socket we knew about before. michael@0: */ michael@0: reset: function() { michael@0: this.binaryInput = null; michael@0: this.input = null; michael@0: this.binaryOutput = null; michael@0: this.output = null; michael@0: }, michael@0: }; michael@0: michael@0: function run_test() { michael@0: Services.prefs.setBoolPref('dom.mozTCPSocket.enabled', true); michael@0: michael@0: do_test_pending(); michael@0: michael@0: server = new TestServer(); michael@0: server.reset(); michael@0: sock = TCPSocket.open( michael@0: '127.0.0.1', server.listener.port, michael@0: { binaryType: 'arraybuffer' }); michael@0: michael@0: var encoder = new TextEncoder(); michael@0: var ok = encoder.encode("OKBYE"); michael@0: michael@0: var expected = ['O', 'K', 'B', 'Y', 'E'] michael@0: .map(function(c) { return c.charCodeAt(0); }); michael@0: var seenData = []; michael@0: michael@0: server.onaccept = function() {}; michael@0: server.ondata = function(data) { michael@0: do_print(data + ":" + data.length); michael@0: michael@0: seenData = seenData.concat(data); michael@0: michael@0: if (seenData.length == expected.length) { michael@0: do_print(expected); michael@0: do_check_eq(seenData.length, expected.length); michael@0: for (var i = 0; i < seenData.length; i++) { michael@0: do_check_eq(seenData[i], expected[i]); michael@0: } michael@0: sock.close(); michael@0: server.close(); michael@0: do_test_finished(); michael@0: } michael@0: }; michael@0: server.onclose = function() {}; michael@0: michael@0: sock.onopen = function() { michael@0: sock.send(ok.buffer, 0, 2); michael@0: sock.send(ok.buffer, 2, 3); michael@0: }; michael@0: }