|
1 const Cc = Components.classes; |
|
2 const Ci = Components.interfaces; |
|
3 const Cr = Components.results; |
|
4 const Cu = Components.utils; |
|
5 const CC = Components.Constructor; |
|
6 |
|
7 Cu.import("resource://gre/modules/Services.jsm"); |
|
8 |
|
9 const ServerSocket = CC("@mozilla.org/network/server-socket;1", |
|
10 "nsIServerSocket", |
|
11 "init"), |
|
12 InputStreamPump = CC("@mozilla.org/network/input-stream-pump;1", |
|
13 "nsIInputStreamPump", |
|
14 "init"), |
|
15 BinaryInputStream = CC("@mozilla.org/binaryinputstream;1", |
|
16 "nsIBinaryInputStream", |
|
17 "setInputStream"), |
|
18 BinaryOutputStream = CC("@mozilla.org/binaryoutputstream;1", |
|
19 "nsIBinaryOutputStream", |
|
20 "setOutputStream"), |
|
21 TCPSocket = new (CC("@mozilla.org/tcp-socket;1", |
|
22 "nsIDOMTCPSocket"))(); |
|
23 |
|
24 var server = null, sock = null; |
|
25 |
|
26 /** |
|
27 * Spin up a listening socket and associate at most one live, accepted socket |
|
28 * with ourselves. |
|
29 */ |
|
30 function TestServer() { |
|
31 this.listener = ServerSocket(-1, true, -1); |
|
32 do_print('server: listening on', this.listener.port); |
|
33 this.listener.asyncListen(this); |
|
34 |
|
35 this.binaryInput = null; |
|
36 this.input = null; |
|
37 this.binaryOutput = null; |
|
38 this.output = null; |
|
39 |
|
40 this.onaccept = null; |
|
41 this.ondata = null; |
|
42 this.onclose = null; |
|
43 } |
|
44 |
|
45 TestServer.prototype = { |
|
46 onSocketAccepted: function(socket, trans) { |
|
47 if (this.input) |
|
48 do_throw("More than one live connection!?"); |
|
49 |
|
50 do_print('server: got client connection'); |
|
51 this.input = trans.openInputStream(0, 0, 0); |
|
52 this.binaryInput = new BinaryInputStream(this.input); |
|
53 this.output = trans.openOutputStream(0, 0, 0); |
|
54 this.binaryOutput = new BinaryOutputStream(this.output); |
|
55 |
|
56 new InputStreamPump(this.input, -1, -1, 0, 0, false).asyncRead(this, null); |
|
57 |
|
58 if (this.onaccept) |
|
59 this.onaccept(); |
|
60 else |
|
61 do_throw("Received unexpected connection!"); |
|
62 }, |
|
63 |
|
64 onStopListening: function(socket) { |
|
65 }, |
|
66 |
|
67 onDataAvailable: function(request, context, inputStream, offset, count) { |
|
68 var readData = this.binaryInput.readByteArray(count); |
|
69 if (this.ondata) { |
|
70 try { |
|
71 this.ondata(readData); |
|
72 } catch(ex) { |
|
73 // re-throw if this is from do_throw |
|
74 if (ex === Cr.NS_ERROR_ABORT) |
|
75 throw ex; |
|
76 // log if there was a test problem |
|
77 do_print('Caught exception: ' + ex + '\n' + ex.stack); |
|
78 do_throw('test is broken; bad ondata handler; see above'); |
|
79 } |
|
80 } else { |
|
81 do_throw('Received ' + count + ' bytes of unexpected data!'); |
|
82 } |
|
83 }, |
|
84 |
|
85 onStartRequest: function(request, context) { |
|
86 }, |
|
87 |
|
88 onStopRequest: function(request, context, status) { |
|
89 if (this.onclose) |
|
90 this.onclose(); |
|
91 else |
|
92 do_throw("Received unexpected close!"); |
|
93 }, |
|
94 |
|
95 close: function() { |
|
96 this.binaryInput.close(); |
|
97 this.binaryOutput.close(); |
|
98 }, |
|
99 |
|
100 /** |
|
101 * Forget about the socket we knew about before. |
|
102 */ |
|
103 reset: function() { |
|
104 this.binaryInput = null; |
|
105 this.input = null; |
|
106 this.binaryOutput = null; |
|
107 this.output = null; |
|
108 }, |
|
109 }; |
|
110 |
|
111 function run_test() { |
|
112 Services.prefs.setBoolPref('dom.mozTCPSocket.enabled', true); |
|
113 |
|
114 do_test_pending(); |
|
115 |
|
116 server = new TestServer(); |
|
117 server.reset(); |
|
118 sock = TCPSocket.open( |
|
119 '127.0.0.1', server.listener.port, |
|
120 { binaryType: 'arraybuffer' }); |
|
121 |
|
122 var encoder = new TextEncoder(); |
|
123 var ok = encoder.encode("OKBYE"); |
|
124 |
|
125 var expected = ['O', 'K', 'B', 'Y', 'E'] |
|
126 .map(function(c) { return c.charCodeAt(0); }); |
|
127 var seenData = []; |
|
128 |
|
129 server.onaccept = function() {}; |
|
130 server.ondata = function(data) { |
|
131 do_print(data + ":" + data.length); |
|
132 |
|
133 seenData = seenData.concat(data); |
|
134 |
|
135 if (seenData.length == expected.length) { |
|
136 do_print(expected); |
|
137 do_check_eq(seenData.length, expected.length); |
|
138 for (var i = 0; i < seenData.length; i++) { |
|
139 do_check_eq(seenData[i], expected[i]); |
|
140 } |
|
141 sock.close(); |
|
142 server.close(); |
|
143 do_test_finished(); |
|
144 } |
|
145 }; |
|
146 server.onclose = function() {}; |
|
147 |
|
148 sock.onopen = function() { |
|
149 sock.send(ok.buffer, 0, 2); |
|
150 sock.send(ok.buffer, 2, 3); |
|
151 }; |
|
152 } |