bug 1119280 - fix large spdy/h2 transfer truncation r=hurley a=lmandel
authorPatrick McManus <mcmanus@ducksong.com>
Fri, 09 Jan 2015 10:18:28 -0500
changeset 249244 b61267bf124e63cac6716bc444b90cbdef9e1c4f
parent 249243 425a17af8a9638485ea2bbb334216b4fb19acfb8
child 249245 8968645dda7983b73ea4420a7110de61213f852b
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershurley, lmandel
bugs1119280
milestone37.0a2
bug 1119280 - fix large spdy/h2 transfer truncation r=hurley a=lmandel
netwerk/protocol/http/ASpdySession.h
netwerk/test/unit/test_http2.js
testing/xpcshell/moz-http2/moz-http2.js
--- a/netwerk/protocol/http/ASpdySession.h
+++ b/netwerk/protocol/http/ASpdySession.h
@@ -50,17 +50,17 @@ public:
   // scenarios.
   const static uint32_t kInitialRwin = 256 * 1024 * 1024;
 
   // soft errors are errors that terminate a stream without terminating the
   // connection. In general non-network errors are stream errors as well
   // as network specific items like cancels.
   bool SoftStreamError(nsresult code)
   {
-    if (NS_SUCCEEDED(code)) {
+    if (NS_SUCCEEDED(code) || code == NS_BASE_STREAM_WOULD_BLOCK) {
       return false;
     }
 
     // this could go either way, but because there are network instances of
     // it being a hard error we should consider it hard.
     if (code == NS_ERROR_FAILURE) {
       return false;
     }
--- a/netwerk/test/unit/test_http2.js
+++ b/netwerk/test/unit/test_http2.js
@@ -169,16 +169,37 @@ Http2BigListener.prototype.onStopRequest
 
   // Don't want to flood output, so don't use do_check_eq
   do_check_true(this.buffer == bigListenerData);
 
   run_next_test();
   do_test_finished();
 };
 
+var Http2HugeSuspendedListener = function() {};
+
+Http2HugeSuspendedListener.prototype = new Http2CheckListener();
+Http2HugeSuspendedListener.prototype.count = 0;
+
+Http2HugeSuspendedListener.prototype.onDataAvailable = function(request, ctx, stream, off, cnt) {
+  this.onDataAvailableFired = true;
+  this.isHttp2Connection = checkIsHttp2(request);
+  this.count += cnt;
+  read_stream(stream, cnt);
+};
+
+Http2HugeSuspendedListener.prototype.onStopRequest = function(request, ctx, status) {
+  do_check_true(this.onStartRequestFired);
+  do_check_true(this.onDataAvailableFired);
+  do_check_true(this.isHttp2Connection);
+  do_check_eq(this.count, 1024 * 1024 * 1); // 1mb of data expected
+  run_next_test();
+  do_test_finished();
+};
+
 // Does the appropriate checks for POSTs
 var Http2PostListener = function(expected_md5) {
   this.expected_md5 = expected_md5;
 };
 
 Http2PostListener.prototype = new Http2CheckListener();
 Http2PostListener.prototype.expected_md5 = "";
 
@@ -328,16 +349,24 @@ function test_http2_doubleheader() {
 
 // Make sure we handle GETs that cover more than 2 frames properly
 function test_http2_big() {
   var chan = makeChan("https://localhost:6944/big");
   var listener = new Http2BigListener();
   chan.asyncOpen(listener, null);
 }
 
+function test_http2_huge_suspended() {
+  var chan = makeChan("https://localhost:6944/huge");
+  var listener = new Http2HugeSuspendedListener();
+  chan.asyncOpen(listener, null);
+  chan.suspend();
+  do_timeout(500, chan.resume);
+}
+
 // Support for doing a POST
 function do_post(content, chan, listener) {
   var stream = Cc["@mozilla.org/io/string-input-stream;1"]
                .createInstance(Ci.nsIStringInputStream);
   stream.data = content;
 
   var uchan = chan.QueryInterface(Ci.nsIUploadChannel);
   uchan.setUploadStream(stream, "text/plain", stream.available());
@@ -560,16 +589,17 @@ var tests = [ test_http2_post_big
             , test_http2_push4
 	    , test_http2_altsvc
             , test_http2_doubleheader
             , test_http2_xhr
             , test_http2_header
             , test_http2_cookie_crumbling
             , test_http2_multiplex
             , test_http2_big
+            , test_http2_huge_suspended
             , test_http2_post
             , test_http2_pushapi_1
             // These next two must always come in this order
             , test_http2_h11required_stream
             , test_http2_h11required_session
             , test_http2_retry_rst
 
             // cleanup
--- a/testing/xpcshell/moz-http2/moz-http2.js
+++ b/testing/xpcshell/moz-http2/moz-http2.js
@@ -222,16 +222,28 @@ function handleRequest(req, res) {
   else if (u.pathname === "/big") {
     content = generateContent(128 * 1024);
     var hash = crypto.createHash('md5');
     hash.update(content);
     var md5 = hash.digest('hex');
     res.setHeader("X-Expected-MD5", md5);
   }
 
+  else if (u.pathname === "/huge") {
+    content = generateContent(1024);
+    res.setHeader('Content-Type', 'text/plain');
+    res.writeHead(200);
+    // 1mb of data
+    for (var i = 0; i < (1024 * 1); i++) {
+      res.write(content); // 1kb chunk
+    }
+    res.end();
+    return;
+  }
+
   else if (u.pathname === "/post") {
     if (req.method != "POST") {
       res.writeHead(405);
       res.end('Unexpected method: ' + req.method);
       return;
     }
 
     var post_hash = crypto.createHash('md5');