зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1337791 - Part 3: http/2 origin frame extension test. r=nwgh
This commit is contained in:
Родитель
06bd9a4bae
Коммит
0ef4fc0939
|
@ -0,0 +1,254 @@
|
|||
Cu.import("resource://testing-common/httpd.js");
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
|
||||
var h2Port;
|
||||
var prefs;
|
||||
var spdypref;
|
||||
var http2pref;
|
||||
|
||||
function run_test() {
|
||||
var env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
|
||||
h2Port = env.get("MOZHTTP2_PORT");
|
||||
do_check_neq(h2Port, null);
|
||||
do_check_neq(h2Port, "");
|
||||
|
||||
// Set to allow the cert presented by our H2 server
|
||||
do_get_profile();
|
||||
prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||
|
||||
spdypref = prefs.getBoolPref("network.http.spdy.enabled");
|
||||
http2pref = prefs.getBoolPref("network.http.spdy.enabled.http2");
|
||||
|
||||
prefs.setBoolPref("network.http.spdy.enabled", true);
|
||||
prefs.setBoolPref("network.http.spdy.enabled.http2", true);
|
||||
prefs.setCharPref("network.dns.localDomains", "foo.example.com, alt1.example.com");
|
||||
|
||||
// The moz-http2 cert is for {foo, alt1, alt2}.example.com and is signed by CA.cert.der
|
||||
// so add that cert to the trust list as a signing cert.
|
||||
let certdb = Cc["@mozilla.org/security/x509certdb;1"]
|
||||
.getService(Ci.nsIX509CertDB);
|
||||
addCertFromFile(certdb, "CA.cert.der", "CTu,u,u");
|
||||
|
||||
doTest1();
|
||||
}
|
||||
|
||||
function resetPrefs() {
|
||||
prefs.setBoolPref("network.http.spdy.enabled", spdypref);
|
||||
prefs.setBoolPref("network.http.spdy.enabled.http2", http2pref);
|
||||
prefs.clearUserPref("network.dns.localDomains");
|
||||
}
|
||||
|
||||
function readFile(file) {
|
||||
let fstream = Cc["@mozilla.org/network/file-input-stream;1"]
|
||||
.createInstance(Ci.nsIFileInputStream);
|
||||
fstream.init(file, -1, 0, 0);
|
||||
let data = NetUtil.readInputStreamToString(fstream, fstream.available());
|
||||
fstream.close();
|
||||
return data;
|
||||
}
|
||||
|
||||
function addCertFromFile(certdb, filename, trustString) {
|
||||
let certFile = do_get_file(filename, false);
|
||||
let der = readFile(certFile);
|
||||
certdb.addCert(der, trustString);
|
||||
}
|
||||
|
||||
function makeChan(origin) {
|
||||
return NetUtil.newChannel({
|
||||
uri: origin,
|
||||
loadUsingSystemPrincipal: true
|
||||
}).QueryInterface(Ci.nsIHttpChannel);
|
||||
}
|
||||
|
||||
var nextTest;
|
||||
var nextPortExpectedToBeSame = false;
|
||||
var currentPort = 0;
|
||||
var forceReload = false;
|
||||
var forceFailListener = false;
|
||||
|
||||
var Listener = function() {};
|
||||
Listener.prototype.clientPort = 0;
|
||||
Listener.prototype = {
|
||||
onStartRequest: function testOnStartRequest(request, ctx) {
|
||||
do_check_true(request instanceof Components.interfaces.nsIHttpChannel);
|
||||
|
||||
if (!Components.isSuccessCode(request.status)) {
|
||||
do_throw("Channel should have a success code! (" + request.status + ")");
|
||||
}
|
||||
do_check_eq(request.responseStatus, 200);
|
||||
this.clientPort = parseInt(request.getResponseHeader("x-client-port"));
|
||||
},
|
||||
|
||||
onDataAvailable: function testOnDataAvailable(request, ctx, stream, off, cnt) {
|
||||
read_stream(stream, cnt);
|
||||
},
|
||||
|
||||
onStopRequest: function testOnStopRequest(request, ctx, status) {
|
||||
do_check_true(Components.isSuccessCode(status));
|
||||
if (nextPortExpectedToBeSame) {
|
||||
do_check_eq(currentPort, this.clientPort);
|
||||
} else {
|
||||
do_check_neq(currentPort, this.clientPort);
|
||||
}
|
||||
currentPort = this.clientPort;
|
||||
nextTest();
|
||||
do_test_finished();
|
||||
}
|
||||
};
|
||||
|
||||
var FailListener = function() {};
|
||||
FailListener.prototype = {
|
||||
onStartRequest: function testOnStartRequest(request, ctx) {
|
||||
do_check_true(request instanceof Components.interfaces.nsIHttpChannel);
|
||||
do_check_false(Components.isSuccessCode(request.status));
|
||||
},
|
||||
onDataAvailable: function testOnDataAvailable(request, ctx, stream, off, cnt) {
|
||||
read_stream(stream, cnt);
|
||||
},
|
||||
onStopRequest: function testOnStopRequest(request, ctx, status) {
|
||||
do_check_false(Components.isSuccessCode(request.status));
|
||||
nextTest();
|
||||
do_test_finished();
|
||||
}
|
||||
};
|
||||
|
||||
function testsDone()
|
||||
{
|
||||
dump("testsDone\n");
|
||||
resetPrefs();
|
||||
}
|
||||
|
||||
function doTest()
|
||||
{
|
||||
dump("execute doTest " + origin + "\n");
|
||||
var chan = makeChan(origin);
|
||||
var listener;
|
||||
if (!forceFailListener) {
|
||||
listener = new Listener();
|
||||
} else {
|
||||
listener = new FailListener();
|
||||
}
|
||||
forceFailListener = false;
|
||||
|
||||
if (!forceReload) {
|
||||
chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
|
||||
} else {
|
||||
chan.loadFlags = Ci.nsIRequest.LOAD_FRESH_CONNECTION |
|
||||
Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
|
||||
}
|
||||
forceReload = false;
|
||||
chan.asyncOpen2(listener);
|
||||
}
|
||||
|
||||
function doTest1()
|
||||
{
|
||||
dump("doTest1()\n");
|
||||
origin = "https://foo.example.com:" + h2Port + "/origin-1";
|
||||
nextTest = doTest2;
|
||||
nextPortExpectedToBeSame = false;
|
||||
do_test_pending();
|
||||
doTest();
|
||||
}
|
||||
|
||||
function doTest2()
|
||||
{
|
||||
// plain connection reuse
|
||||
dump("doTest2()\n");
|
||||
origin = "https://foo.example.com:" + h2Port + "/origin-2";
|
||||
nextTest = doTest3;
|
||||
nextPortExpectedToBeSame = true;
|
||||
do_test_pending();
|
||||
doTest();
|
||||
}
|
||||
|
||||
function doTest3()
|
||||
{
|
||||
// 7540 style coalescing
|
||||
dump("doTest3()\n");
|
||||
origin = "https://alt1.example.com:" + h2Port + "/origin-3";
|
||||
nextTest = doTest4;
|
||||
nextPortExpectedToBeSame = true;
|
||||
do_test_pending();
|
||||
doTest();
|
||||
}
|
||||
|
||||
function doTest4()
|
||||
{
|
||||
// forces an empty origin frame to be omitted
|
||||
dump("doTest4()\n");
|
||||
origin = "https://foo.example.com:" + h2Port + "/origin-4";
|
||||
nextTest = doTest5;
|
||||
nextPortExpectedToBeSame = true;
|
||||
do_test_pending();
|
||||
doTest();
|
||||
}
|
||||
|
||||
function doTest5()
|
||||
{
|
||||
// 7540 style coalescing should not work due to empty origin set
|
||||
dump("doTest5()\n");
|
||||
origin = "https://alt1.example.com:" + h2Port + "/origin-5";
|
||||
nextTest = doTest6;
|
||||
nextPortExpectedToBeSame = false;
|
||||
do_test_pending();
|
||||
doTest();
|
||||
}
|
||||
|
||||
function doTest6()
|
||||
{
|
||||
// get a fresh connection with alt1 and alt2 in origin set
|
||||
// note that there is no dns for alt2
|
||||
dump("doTest6()\n");
|
||||
origin = "https://foo.example.com:" + h2Port + "/origin-6";
|
||||
nextTest = doTest7;
|
||||
nextPortExpectedToBeSame = false;
|
||||
forceReload = true;
|
||||
do_test_pending();
|
||||
doTest();
|
||||
}
|
||||
|
||||
function doTest7()
|
||||
{
|
||||
// check conn reuse to ensure sni is implicit in origin set
|
||||
dump("doTest7()\n");
|
||||
origin = "https://foo.example.com:" + h2Port + "/origin-7";
|
||||
nextTest = doTest8;
|
||||
nextPortExpectedToBeSame = true;
|
||||
do_test_pending();
|
||||
doTest();
|
||||
}
|
||||
|
||||
function doTest8()
|
||||
{
|
||||
// alt1 is in origin set (and is 7540 eligible)
|
||||
dump("doTest8()\n");
|
||||
origin = "https://alt1.example.com:" + h2Port + "/origin-8";
|
||||
nextTest = doTest9;
|
||||
nextPortExpectedToBeSame = true;
|
||||
do_test_pending();
|
||||
doTest();
|
||||
}
|
||||
|
||||
function doTest9()
|
||||
{
|
||||
// alt2 is in origin set but does not have dns
|
||||
dump("doTest9()\n");
|
||||
origin = "https://alt2.example.com:" + h2Port + "/origin-9";
|
||||
nextTest = doTest10;
|
||||
nextPortExpectedToBeSame = true;
|
||||
do_test_pending();
|
||||
doTest();
|
||||
}
|
||||
|
||||
function doTest10()
|
||||
{
|
||||
// bar is in origin set but does not have dns like alt2
|
||||
// but the cert is not valid for bar. so expect a failure
|
||||
dump("doTest10()\n");
|
||||
origin = "https://bar.example.com:" + h2Port + "/origin-10";
|
||||
nextTest = testsDone;
|
||||
nextPortExpectedToBeSame = false;
|
||||
forceFailListener = true;
|
||||
do_test_pending();
|
||||
doTest();
|
||||
}
|
|
@ -250,6 +250,7 @@ run-sequentially = node server exceptions dont replay well
|
|||
skip-if = os == "win"
|
||||
[test_nojsredir.js]
|
||||
[test_offline_status.js]
|
||||
[test_origin.js]
|
||||
[test_original_sent_received_head.js]
|
||||
[test_parse_content_type.js]
|
||||
[test_permmgr.js]
|
||||
|
|
|
@ -1,79 +1,24 @@
|
|||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number: 1 (0x1)
|
||||
Signature Algorithm: sha256WithRSAEncryption
|
||||
Issuer: C=US, ST=Maine, O=CA Example
|
||||
Validity
|
||||
Not Before: Apr 29 05:29:19 2015 GMT
|
||||
Not After : Apr 26 05:29:19 2025 GMT
|
||||
Subject: C=US, ST=Maine, O=Example Com, CN=foo.example.com
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
Public-Key: (2048 bit)
|
||||
Modulus:
|
||||
00:cf:ff:c0:27:3b:a3:11:b5:7f:5d:4f:22:f9:75:
|
||||
48:47:d9:3a:ce:9b:66:82:4e:e4:ae:ab:78:d3:4c:
|
||||
3a:9a:5c:37:97:b2:7b:4e:2a:54:77:16:2a:3e:6f:
|
||||
52:ee:4b:49:46:1d:6b:18:9a:ed:b1:ad:64:9f:8b:
|
||||
e5:fa:e4:60:7b:39:0e:db:e8:b4:2d:4b:e8:ab:37:
|
||||
e8:90:ec:eb:0f:3e:6b:40:7a:d1:da:e6:68:b3:f4:
|
||||
f6:68:54:5b:27:90:6d:c2:c3:04:de:85:23:2b:3c:
|
||||
66:4e:06:79:58:93:a1:71:d7:ec:74:55:a4:84:9d:
|
||||
41:22:2a:7a:76:ae:56:b1:6f:15:2d:f2:f5:9c:64:
|
||||
3e:4f:0f:6e:8f:b6:28:66:e9:89:04:5d:1d:21:77:
|
||||
f8:03:d3:89:ed:7c:f4:3b:42:02:c8:8d:de:47:74:
|
||||
1f:4a:5d:fe:8d:d1:57:37:08:54:bf:89:d8:f7:27:
|
||||
22:a7:2a:5d:aa:d5:b0:61:22:9b:96:75:ee:ab:09:
|
||||
ca:a9:cb:2b:1e:88:7c:5a:53:7e:5f:88:c4:43:ea:
|
||||
e8:a7:db:35:6c:b2:89:ad:98:e0:96:c9:83:c4:c1:
|
||||
e7:2a:5c:f8:99:5c:9e:01:9c:e6:99:bd:18:5c:69:
|
||||
d4:10:f1:46:88:37:0b:4e:76:5f:6a:1a:21:c2:a4:
|
||||
16:d1
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Subject Key Identifier:
|
||||
76:BC:13:90:F7:85:1B:1C:24:A1:CC:65:8A:4F:4C:0C:7F:10:D3:F5
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:F7:FC:76:AF:C5:1A:E9:C9:42:6C:38:DF:8B:07:9E:2B:2C:E5:8E:20
|
||||
|
||||
X509v3 Basic Constraints:
|
||||
CA:FALSE
|
||||
X509v3 Key Usage:
|
||||
Digital Signature, Key Encipherment
|
||||
Signature Algorithm: sha256WithRSAEncryption
|
||||
03:ab:2a:9e:e5:cd:5c:88:5a:6c:f7:4b:7a:7c:ef:85:2c:31:
|
||||
df:03:79:31:a6:c5:c8:2b:c6:21:a5:33:2b:a0:4b:e2:7e:0a:
|
||||
86:9b:72:25:b6:75:43:41:7c:30:9f:15:b4:9f:34:50:57:eb:
|
||||
87:f9:1e:9f:b6:cd:81:36:92:61:66:d5:fe:e2:c5:ed:de:f1:
|
||||
ce:85:0b:f9:6a:2b:32:4d:29:f1:a9:94:57:a3:0f:74:93:12:
|
||||
c9:0a:28:5e:72:9f:4f:0f:78:f5:84:11:5a:9f:d7:1c:4c:fd:
|
||||
13:d8:3d:4c:f8:dd:4c:c6:1c:fd:63:ee:f5:d5:96:f5:00:2c:
|
||||
e6:bb:c9:4c:d8:6a:19:59:58:2b:d4:05:ab:57:47:1c:49:d6:
|
||||
c5:56:1a:e3:64:10:19:9b:44:3e:74:8b:19:73:28:86:96:b4:
|
||||
d1:2a:49:23:07:25:97:64:8f:1b:1c:64:76:12:e0:df:e3:cf:
|
||||
55:d5:7c:e9:77:d4:69:2f:c7:9a:fd:ce:1a:29:ab:d7:88:68:
|
||||
93:de:75:e4:d6:85:29:e2:b6:b7:59:20:e3:b5:20:b7:e8:0b:
|
||||
23:9b:4c:b4:e8:d9:90:cf:e9:2f:9e:a8:22:a2:ef:6a:68:65:
|
||||
f6:c4:81:ed:75:77:88:01:f2:47:03:1a:de:1f:44:38:47:fa:
|
||||
aa:69:f2:98
|
||||
-----BEGIN CERTIFICATE-----
|
||||
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
|
||||
J3i97uzqNXPwTFMu3Q==
|
||||
-----END CERTIFICATE-----
|
||||
|
|
|
@ -743,6 +743,21 @@ function handleRequest(req, res) {
|
|||
}
|
||||
// default response from here
|
||||
}
|
||||
else if (u.pathname === "/origin-4") {
|
||||
var originList = [ ];
|
||||
req.stream.connection.originFrame(originList);
|
||||
res.setHeader("x-client-port", req.remotePort);
|
||||
}
|
||||
else if (u.pathname === "/origin-6") {
|
||||
var originList = [ "https://alt1.example.com:" + serverPort,
|
||||
"https://alt2.example.com:" + serverPort,
|
||||
"https://bar.example.com:" + serverPort ];
|
||||
req.stream.connection.originFrame(originList);
|
||||
res.setHeader("x-client-port", req.remotePort);
|
||||
}
|
||||
else if (u.pathname.substring(0,8) === "/origin-") { // test_origin.js coalescing
|
||||
res.setHeader("x-client-port", req.remotePort);
|
||||
}
|
||||
|
||||
res.setHeader('Content-Type', 'text/html');
|
||||
if (req.httpVersionMajor != 2) {
|
||||
|
|
|
@ -123,7 +123,7 @@ Connection.prototype._initializeStreamManagement = function _initializeStreamMan
|
|||
Connection.prototype._writeControlFrame = function _writeControlFrame(frame) {
|
||||
if ((frame.type === 'SETTINGS') || (frame.type === 'PING') ||
|
||||
(frame.type === 'GOAWAY') || (frame.type === 'WINDOW_UPDATE') ||
|
||||
(frame.type === 'ALTSVC')) {
|
||||
(frame.type === 'ALTSVC') || (frame.type == 'ORIGIN')) {
|
||||
this._log.debug({ frame: frame }, 'Receiving connection level frame');
|
||||
this.emit(frame.type, frame);
|
||||
} else {
|
||||
|
@ -557,6 +557,17 @@ Connection.prototype._receivePing = function _receivePing(frame) {
|
|||
}
|
||||
};
|
||||
|
||||
Connection.prototype.originFrame = function originFrame(originList) {
|
||||
this._log.debug(originList, 'emitting origin frame');
|
||||
|
||||
this.push({
|
||||
type: 'ORIGIN',
|
||||
flags: {},
|
||||
stream: 0,
|
||||
originList : originList,
|
||||
});
|
||||
};
|
||||
|
||||
// Terminating the connection
|
||||
Connection.prototype.close = function close(error) {
|
||||
if (this._closed) {
|
||||
|
|
|
@ -64,7 +64,6 @@ function Flow(flowControlId) {
|
|||
this._queue = [];
|
||||
this._ended = false;
|
||||
this._received = 0;
|
||||
this._blocked = false;
|
||||
}
|
||||
Flow.prototype = Object.create(Duplex.prototype, { constructor: { value: Flow } });
|
||||
|
||||
|
@ -157,7 +156,6 @@ Flow.prototype._read = function _read() {
|
|||
// * if there are items in the flow control queue, then let's put them into the output queue (to
|
||||
// the extent it is possible with respect to the window size and output queue feedback)
|
||||
else if (this._window > 0) {
|
||||
this._blocked = false;
|
||||
this._readableState.sync = true; // to avoid reentrant calls
|
||||
do {
|
||||
var moreNeeded = this._push(this._queue[0]);
|
||||
|
@ -173,14 +171,8 @@ Flow.prototype._read = function _read() {
|
|||
}
|
||||
|
||||
// * otherwise, come back when the flow control window is positive
|
||||
else if (!this._blocked) {
|
||||
this._parentPush({
|
||||
type: 'BLOCKED',
|
||||
flags: {},
|
||||
stream: this._flowControlId
|
||||
});
|
||||
else {
|
||||
this.once('window_update', this._read);
|
||||
this._blocked = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1069,26 +1069,24 @@ Deserializer.ALTSVC = function readAltSvc(buffer, frame) {
|
|||
}
|
||||
};
|
||||
|
||||
// BLOCKED
|
||||
// ------------------------------------------------------------
|
||||
//
|
||||
// The BLOCKED frame (type=0xB) indicates that the sender is unable to send data
|
||||
// due to a closed flow control window.
|
||||
//
|
||||
// The BLOCKED frame does not define any flags and contains no payload.
|
||||
frameTypes[0xB] = 'ORIGIN';
|
||||
frameFlags.ORIGIN = [];
|
||||
typeSpecificAttributes.ORIGIN = ['originList'];
|
||||
|
||||
frameTypes[0xB] = 'BLOCKED';
|
||||
|
||||
frameFlags.BLOCKED = [];
|
||||
|
||||
typeSpecificAttributes.BLOCKED = [];
|
||||
|
||||
Serializer.BLOCKED = function writeBlocked(frame, buffers) {
|
||||
Serializer.ORIGIN = function writeOrigin(frame, buffers) {
|
||||
for (var i = 0; i < frame.originList.length; i++) {
|
||||
var buffer = new Buffer(2);
|
||||
buffer.writeUInt16BE(frame.originList[i].length, 0);
|
||||
buffers.push(buffer);
|
||||
buffers.push(new Buffer(frame.originList[i], 'ascii'));
|
||||
}
|
||||
};
|
||||
|
||||
Deserializer.BLOCKED = function readBlocked(buffer, frame) {
|
||||
Deserializer.ORIGIN = function readOrigin(buffer, frame) {
|
||||
// ignored
|
||||
};
|
||||
|
||||
|
||||
// [Error Codes](https://tools.ietf.org/html/rfc7540#section-7)
|
||||
// ------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -253,7 +253,7 @@ Stream.prototype._writeUpstream = function _writeUpstream(frame) {
|
|||
this._onPriority(frame);
|
||||
} else if (frame.type === 'ALTSVC') {
|
||||
// TODO
|
||||
} else if (frame.type === 'BLOCKED') {
|
||||
} else if (frame.type === 'ORIGIN') {
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
@ -413,7 +413,7 @@ Stream.prototype._transition = function transition(sending, frame) {
|
|||
var connectionError;
|
||||
var streamError;
|
||||
|
||||
var DATA = false, HEADERS = false, PRIORITY = false, ALTSVC = false, BLOCKED = false;
|
||||
var DATA = false, HEADERS = false, PRIORITY = false, ALTSVC = false, ORIGIN = false;
|
||||
var RST_STREAM = false, PUSH_PROMISE = false, WINDOW_UPDATE = false;
|
||||
switch(frame.type) {
|
||||
case 'DATA' : DATA = true; break;
|
||||
|
@ -423,7 +423,7 @@ Stream.prototype._transition = function transition(sending, frame) {
|
|||
case 'PUSH_PROMISE' : PUSH_PROMISE = true; break;
|
||||
case 'WINDOW_UPDATE': WINDOW_UPDATE = true; break;
|
||||
case 'ALTSVC' : ALTSVC = true; break;
|
||||
case 'BLOCKED' : BLOCKED = true; break;
|
||||
case 'ORIGIN' : ORIGIN = true; break;
|
||||
}
|
||||
|
||||
var previousState = this.state;
|
||||
|
@ -483,7 +483,7 @@ Stream.prototype._transition = function transition(sending, frame) {
|
|||
this._setState('CLOSED');
|
||||
} else if (receiving && HEADERS) {
|
||||
this._setState('HALF_CLOSED_LOCAL');
|
||||
} else if (BLOCKED || PRIORITY) {
|
||||
} else if (PRIORITY || ORIGIN) {
|
||||
/* No state change */
|
||||
} else {
|
||||
connectionError = 'PROTOCOL_ERROR';
|
||||
|
@ -518,7 +518,7 @@ Stream.prototype._transition = function transition(sending, frame) {
|
|||
case 'HALF_CLOSED_LOCAL':
|
||||
if (RST_STREAM || (receiving && frame.flags.END_STREAM)) {
|
||||
this._setState('CLOSED');
|
||||
} else if (BLOCKED || ALTSVC || receiving || PRIORITY || (sending && WINDOW_UPDATE)) {
|
||||
} else if (ORIGIN || ALTSVC || receiving || PRIORITY || (sending && WINDOW_UPDATE)) {
|
||||
/* No state change */
|
||||
} else {
|
||||
connectionError = 'PROTOCOL_ERROR';
|
||||
|
@ -538,7 +538,7 @@ Stream.prototype._transition = function transition(sending, frame) {
|
|||
case 'HALF_CLOSED_REMOTE':
|
||||
if (RST_STREAM || (sending && frame.flags.END_STREAM)) {
|
||||
this._setState('CLOSED');
|
||||
} else if (BLOCKED || ALTSVC || sending || PRIORITY || (receiving && WINDOW_UPDATE)) {
|
||||
} else if (ORIGIN || ALTSVC || sending || PRIORITY || (receiving && WINDOW_UPDATE)) {
|
||||
/* No state change */
|
||||
} else {
|
||||
connectionError = 'PROTOCOL_ERROR';
|
||||
|
@ -569,7 +569,7 @@ Stream.prototype._transition = function transition(sending, frame) {
|
|||
if (PRIORITY || (sending && RST_STREAM) ||
|
||||
(receiving && WINDOW_UPDATE) ||
|
||||
(receiving && this._closedByUs &&
|
||||
(this._closedWithRst || RST_STREAM || ALTSVC))) {
|
||||
(this._closedWithRst || RST_STREAM || ALTSVC || ORIGIN))) {
|
||||
/* No state change */
|
||||
} else {
|
||||
streamError = 'STREAM_CLOSED';
|
||||
|
|
Загрузка…
Ссылка в новой задаче