Skip to content

Commit 31ed59d

Browse files
committed
Bug 1767298 - Make the behavior of TLSTransportLayer more like SocketTransport, r=necko-reviewers,valentin
Differential Revision: https://phabricator.services.mozilla.com/D163438
1 parent 77c721a commit 31ed59d

File tree

5 files changed

+245
-16
lines changed

5 files changed

+245
-16
lines changed

netwerk/protocol/http/TLSTransportLayer.cpp

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,16 @@ TLSTransportLayer::InputStreamWrapper::Read(char* buf, uint32_t count,
6060
uint32_t* countRead) {
6161
LOG(("TLSTransportLayer::InputStreamWrapper::Read [this=%p]\n", this));
6262

63-
mStatus = NS_OK;
63+
*countRead = 0;
64+
65+
if (NS_FAILED(mStatus)) {
66+
return (mStatus == NS_BASE_STREAM_CLOSED) ? NS_OK : mStatus;
67+
}
68+
6469
int32_t bytesRead = PR_Read(mTransport->mFD, buf, count);
65-
if (bytesRead == -1) {
70+
if (bytesRead > 0) {
71+
*countRead = bytesRead;
72+
} else if (bytesRead < 0) {
6673
PRErrorCode code = PR_GetError();
6774
if (code == PR_WOULD_BLOCK_ERROR) {
6875
LOG((
@@ -78,9 +85,7 @@ TLSTransportLayer::InputStreamWrapper::Read(char* buf, uint32_t count,
7885
".\n",
7986
this, static_cast<uint32_t>(mStatus)));
8087
}
81-
return mStatus;
8288
}
83-
*countRead = bytesRead;
8489

8590
if (NS_SUCCEEDED(mStatus) && !bytesRead) {
8691
LOG(
@@ -203,15 +208,20 @@ TLSTransportLayer::OutputStreamWrapper::Write(const char* buf, uint32_t count,
203208
this, count));
204209

205210
*countWritten = 0;
206-
mStatus = NS_OK;
211+
212+
if (NS_FAILED(mStatus)) {
213+
return (mStatus == NS_BASE_STREAM_CLOSED) ? NS_OK : mStatus;
214+
}
207215

208216
int32_t written = PR_Write(mTransport->mFD, buf, count);
209217
LOG(
210218
("TLSTransportLayer::OutputStreamWrapper::Write %p PRWrite(%d) = %d "
211219
"%d\n",
212220
this, count, written, PR_GetError() == PR_WOULD_BLOCK_ERROR));
213221

214-
if (written < 0) {
222+
if (written > 0) {
223+
*countWritten = written;
224+
} else if (written < 0) {
215225
PRErrorCode code = PR_GetError();
216226
if (code == PR_WOULD_BLOCK_ERROR) {
217227
LOG(
@@ -225,11 +235,8 @@ TLSTransportLayer::OutputStreamWrapper::Write(const char* buf, uint32_t count,
225235
if (NS_SUCCEEDED(mStatus)) {
226236
mStatus = ErrorAccordingToNSPR(code);
227237
}
228-
229-
return mStatus;
230238
}
231239

232-
*countWritten = written;
233240
return mStatus;
234241
}
235242

@@ -690,7 +697,6 @@ int32_t TLSTransportLayer::OutputInternal(const char* aBuf, int32_t aAmount) {
690697

691698
uint32_t outCountWrite = 0;
692699
nsresult rv = mSocketOutWrapper.WriteDirectly(aBuf, aAmount, &outCountWrite);
693-
mSocketOutWrapper.SetStatus(rv);
694700
if (NS_FAILED(rv)) {
695701
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
696702
PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
@@ -708,7 +714,6 @@ int32_t TLSTransportLayer::InputInternal(char* aBuf, int32_t aAmount) {
708714

709715
uint32_t outCountRead = 0;
710716
nsresult rv = mSocketInWrapper.ReadDirectly(aBuf, aAmount, &outCountRead);
711-
mSocketInWrapper.SetStatus(rv);
712717
if (NS_FAILED(rv)) {
713718
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
714719
PR_SetError(PR_WOULD_BLOCK_ERROR, 0);

netwerk/protocol/websocket/WebSocketChannel.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4152,18 +4152,19 @@ WebSocketChannel::OnOutputStreamReady(nsIAsyncOutputStream* aStream) {
41524152
toSend = mCurrentOut->Length() - mCurrentOutSent;
41534153
if (toSend > 0) {
41544154
LOG(
4155-
("WebSocketChannel::OnOutputStreamReady: "
4155+
("WebSocketChannel::OnOutputStreamReady [%p]: "
41564156
"Try to send %u of data\n",
4157-
toSend));
4157+
this, toSend));
41584158
}
41594159
}
41604160

41614161
if (toSend == 0) {
41624162
amtSent = 0;
41634163
} else {
41644164
rv = mSocketOut->Write(sndBuf, toSend, &amtSent);
4165-
LOG(("WebSocketChannel::OnOutputStreamReady: write %u rv %" PRIx32 "\n",
4166-
amtSent, static_cast<uint32_t>(rv)));
4165+
LOG(("WebSocketChannel::OnOutputStreamReady [%p]: write %u rv %" PRIx32
4166+
"\n",
4167+
this, amtSent, static_cast<uint32_t>(rv)));
41674168

41684169
if (rv == NS_BASE_STREAM_WOULD_BLOCK) {
41694170
mSocketOut->AsyncWait(this, 0, 0, mIOThread);

netwerk/test/unit/head_servers.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,6 @@ class WebSocketConnection {
805805

806806
onAcknowledge(aContext, aSize) {}
807807
onBinaryMessageAvailable(aContext, aMsg) {
808-
info(`received binary ${aMsg}`);
809808
this._messages.push(aMsg);
810809
this._msgCallback();
811810
}
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
"use strict";
6+
7+
/* import-globals-from head_cache.js */
8+
/* import-globals-from head_cookies.js */
9+
/* import-globals-from head_channels.js */
10+
/* import-globals-from head_servers.js */
11+
12+
XPCOMUtils.defineLazyModuleGetters(this, {
13+
ObjectUtils: "resource://gre/modules/ObjectUtils.jsm",
14+
});
15+
16+
add_setup(async function() {
17+
Services.prefs.setCharPref("network.dns.localDomains", "foo.example.com");
18+
19+
let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
20+
Ci.nsIX509CertDB
21+
);
22+
addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
23+
addCertFromFile(certdb, "proxy-ca.pem", "CTu,u,u");
24+
});
25+
26+
registerCleanupFunction(async () => {
27+
Services.prefs.clearUserPref("network.dns.localDomains");
28+
});
29+
30+
async function channelOpenPromise(url, msg) {
31+
let conn = new WebSocketConnection();
32+
await conn.open(url);
33+
conn.send(msg);
34+
let res = await conn.receiveMessages();
35+
conn.close();
36+
let { status } = await conn.finished();
37+
return [status, res];
38+
}
39+
40+
async function sendDataAndCheck(url) {
41+
let data = "a".repeat(500000);
42+
let [status, res] = await channelOpenPromise(url, data);
43+
Assert.equal(status, Cr.NS_OK);
44+
// Use "ObjectUtils.deepEqual" directly to avoid printing data.
45+
Assert.ok(ObjectUtils.deepEqual(res, [data]));
46+
}
47+
48+
add_task(async function test_h2_websocket_500k() {
49+
Services.prefs.setBoolPref("network.http.http2.websockets", true);
50+
let wss = new NodeWebSocketHttp2Server();
51+
await wss.start();
52+
registerCleanupFunction(async () => wss.stop());
53+
54+
Assert.notEqual(wss.port(), null);
55+
await wss.registerMessageHandler((data, ws) => {
56+
ws.send(data);
57+
});
58+
let url = `wss://foo.example.com:${wss.port()}`;
59+
await sendDataAndCheck(url);
60+
});
61+
62+
// h1.1 direct
63+
add_task(async function test_h1_websocket_direct() {
64+
let wss = new NodeWebSocketServer();
65+
await wss.start();
66+
registerCleanupFunction(async () => wss.stop());
67+
Assert.notEqual(wss.port(), null);
68+
await wss.registerMessageHandler((data, ws) => {
69+
ws.send(data);
70+
});
71+
let url = `wss://localhost:${wss.port()}`;
72+
await sendDataAndCheck(url);
73+
});
74+
75+
// ws h1.1 with insecure h1.1 proxy
76+
add_task(async function test_h1_ws_with_h1_insecure_proxy() {
77+
Services.prefs.setBoolPref("network.http.http2.websockets", false);
78+
let proxy = new NodeHTTPProxyServer();
79+
await proxy.start();
80+
81+
let wss = new NodeWebSocketServer();
82+
await wss.start();
83+
84+
registerCleanupFunction(async () => {
85+
await wss.stop();
86+
await proxy.stop();
87+
});
88+
89+
Assert.notEqual(wss.port(), null);
90+
91+
await wss.registerMessageHandler((data, ws) => {
92+
ws.send(data);
93+
});
94+
let url = `wss://localhost:${wss.port()}`;
95+
await sendDataAndCheck(url);
96+
});
97+
98+
// h1 server with secure h1.1 proxy
99+
add_task(async function test_h1_ws_with_secure_h1_proxy() {
100+
let proxy = new NodeHTTPSProxyServer();
101+
await proxy.start();
102+
103+
let wss = new NodeWebSocketServer();
104+
await wss.start();
105+
registerCleanupFunction(async () => {
106+
await wss.stop();
107+
await proxy.stop();
108+
});
109+
110+
Assert.notEqual(wss.port(), null);
111+
await wss.registerMessageHandler((data, ws) => {
112+
ws.send(data);
113+
});
114+
115+
let url = `wss://localhost:${wss.port()}`;
116+
await sendDataAndCheck(url);
117+
118+
await proxy.stop();
119+
});
120+
121+
// ws h1.1 with h2 proxy
122+
add_task(async function test_h1_ws_with_h2_proxy() {
123+
Services.prefs.setBoolPref("network.http.http2.websockets", false);
124+
125+
let proxy = new NodeHTTP2ProxyServer();
126+
await proxy.start();
127+
128+
let wss = new NodeWebSocketServer();
129+
await wss.start();
130+
131+
registerCleanupFunction(async () => {
132+
await wss.stop();
133+
await proxy.stop();
134+
});
135+
136+
Assert.notEqual(wss.port(), null);
137+
await wss.registerMessageHandler((data, ws) => {
138+
ws.send(data);
139+
});
140+
141+
let url = `wss://localhost:${wss.port()}`;
142+
await sendDataAndCheck(url);
143+
144+
await proxy.stop();
145+
});
146+
147+
// ws h2 with insecure h1.1 proxy
148+
add_task(async function test_h2_ws_with_h1_insecure_proxy() {
149+
Services.prefs.setBoolPref("network.http.http2.websockets", true);
150+
151+
let proxy = new NodeHTTPProxyServer();
152+
await proxy.start();
153+
154+
let wss = new NodeWebSocketHttp2Server();
155+
await wss.start();
156+
157+
registerCleanupFunction(async () => {
158+
await wss.stop();
159+
await proxy.stop();
160+
});
161+
162+
Assert.notEqual(wss.port(), null);
163+
await wss.registerMessageHandler((data, ws) => {
164+
ws.send(data);
165+
});
166+
167+
let url = `wss://localhost:${wss.port()}`;
168+
await sendDataAndCheck(url);
169+
170+
await proxy.stop();
171+
});
172+
173+
add_task(async function test_h2_ws_with_h1_secure_proxy() {
174+
Services.prefs.setBoolPref("network.http.http2.websockets", true);
175+
176+
let proxy = new NodeHTTPSProxyServer();
177+
await proxy.start();
178+
179+
let wss = new NodeWebSocketHttp2Server();
180+
await wss.start();
181+
182+
registerCleanupFunction(async () => {
183+
await wss.stop();
184+
await proxy.stop();
185+
});
186+
187+
Assert.notEqual(wss.port(), null);
188+
await wss.registerMessageHandler((data, ws) => {
189+
ws.send(data);
190+
});
191+
192+
let url = `wss://localhost:${wss.port()}`;
193+
await sendDataAndCheck(url);
194+
195+
await proxy.stop();
196+
});
197+
198+
// ws h2 with secure h2 proxy
199+
add_task(async function test_h2_ws_with_h2_proxy() {
200+
Services.prefs.setBoolPref("network.http.http2.websockets", true);
201+
202+
let proxy = new NodeHTTP2ProxyServer();
203+
await proxy.start(); // start and register proxy "filter"
204+
205+
let wss = new NodeWebSocketServer();
206+
await wss.start(); // init port
207+
208+
registerCleanupFunction(async () => {
209+
await wss.stop();
210+
await proxy.stop();
211+
});
212+
213+
Assert.notEqual(wss.port(), null);
214+
await wss.registerMessageHandler((data, ws) => {
215+
ws.send(data);
216+
});
217+
218+
let url = `wss://localhost:${wss.port()}`;
219+
await sendDataAndCheck(url);
220+
221+
await proxy.stop();
222+
});

netwerk/test/unit/xpcshell.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,3 +683,5 @@ head = head_channels.js head_cache.js head_cookies.js head_trr.js head_http3.js
683683
skip-if = os == 'android'
684684
run-sequentially = http3server
685685
[test_ohttp.js]
686+
[test_websocket_500k.js]
687+
run-sequentially = node server exceptions dont replay well

0 commit comments

Comments
 (0)