Add parameter to OnCanCreateNewStream indicating directionality

Added a parameter to OnCanCreateNewStream to indicate whether the
available streams are unidirectional or not.

gfe-relnote: N/A is for IETF QUIC (v99 flag protected) only.
PiperOrigin-RevId: 258824808
Change-Id: Ib5f36b81afa35f26fd0ce77e499b51b4a12627b5
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index 7fa925d..e5650a9 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -870,7 +870,9 @@
       !VersionHasIetfQuicFrames(connection_->transport_version())) {
     // Streams that first became draining already called OnCanCreate...
     // This covers the case where the stream went directly to being closed.
-    OnCanCreateNewOutgoingStream();
+    // called with unidirectional false because this is for Google QUIC, which
+    // supports only bidirectional streams.
+    OnCanCreateNewOutgoingStream(false);
   }
 }
 
@@ -926,7 +928,7 @@
       v99_streamid_manager_.OnStreamClosed(stream_id);
     }
   } else if (!VersionHasIetfQuicFrames(connection_->transport_version())) {
-    OnCanCreateNewOutgoingStream();
+    OnCanCreateNewOutgoingStream(false);
   }
 }
 
@@ -1271,7 +1273,16 @@
   }
   if (!IsIncomingStream(stream_id)) {
     // Inform application that a stream is available.
-    OnCanCreateNewOutgoingStream();
+    if (VersionHasIetfQuicFrames(connection_->transport_version())) {
+      if (QuicUtils::IsBidirectionalStreamId(stream_id)) {
+        OnCanCreateNewOutgoingStream(false);
+      } else {
+        OnCanCreateNewOutgoingStream(true);
+      }
+    } else {
+      // Google QUIC has only bidirectional streams.
+      OnCanCreateNewOutgoingStream(false);
+    }
   }
 }
 
@@ -1856,7 +1867,7 @@
   control_frame_manager_.WriteOrBufferStopSending(code, stream_id);
 }
 
-void QuicSession::OnCanCreateNewOutgoingStream() {}
+void QuicSession::OnCanCreateNewOutgoingStream(bool /*unidirectional*/) {}
 
 QuicStreamId QuicSession::next_outgoing_bidirectional_stream_id() const {
   if (VersionHasIetfQuicFrames(connection_->transport_version())) {
diff --git a/quic/core/quic_session.h b/quic/core/quic_session.h
index 24060e8..b7c0212 100644
--- a/quic/core/quic_session.h
+++ b/quic/core/quic_session.h
@@ -393,8 +393,11 @@
 
   // Called when new outgoing streams are available to be opened. This occurs
   // when an extant, open, stream is moved to draining or closed. The default
-  // implementation does nothing.
-  virtual void OnCanCreateNewOutgoingStream();
+  // implementation does nothing. |unidirectional| indicates whether
+  // unidirectional or bidirectional streams are now available. If both become
+  // available at the same time then there will be two calls to this method, one
+  // with unidirectional==true, the other with it ==false.
+  virtual void OnCanCreateNewOutgoingStream(bool unidirectional);
 
   QuicStreamId next_outgoing_bidirectional_stream_id() const;
   QuicStreamId next_outgoing_unidirectional_stream_id() const;
diff --git a/quic/core/quic_session_test.cc b/quic/core/quic_session_test.cc
index ebb17b9..90577d5 100644
--- a/quic/core/quic_session_test.cc
+++ b/quic/core/quic_session_test.cc
@@ -259,7 +259,7 @@
     return consumed;
   }
 
-  MOCK_METHOD0(OnCanCreateNewOutgoingStream, void());
+  MOCK_METHOD1(OnCanCreateNewOutgoingStream, void(bool unidirectional));
 
   void set_writev_consumes_all_data(bool val) {
     writev_consumes_all_data_ = val;
@@ -1693,7 +1693,7 @@
   QuicStreamId stream_id = stream->id();
   QuicStreamFrame data1(stream_id, true, 0, QuicStringPiece("HT"));
   session_.OnStreamFrame(data1);
-  EXPECT_CALL(session_, OnCanCreateNewOutgoingStream()).Times(1);
+  EXPECT_CALL(session_, OnCanCreateNewOutgoingStream(false)).Times(1);
   session_.StreamDraining(stream_id);
 }
 
@@ -1910,13 +1910,13 @@
 
   EXPECT_CALL(*connection_, SendControlFrame(_));
   EXPECT_CALL(*connection_, OnStreamReset(stream2->id(), _));
-  EXPECT_CALL(session_, OnCanCreateNewOutgoingStream()).Times(0);
+  EXPECT_CALL(session_, OnCanCreateNewOutgoingStream(false)).Times(0);
   stream2->Reset(quic::QUIC_STREAM_CANCELLED);
 
   QuicRstStreamFrame rst1(kInvalidControlFrameId, stream2->id(),
                           QUIC_ERROR_PROCESSING_STREAM, 0);
   if (!VersionHasIetfQuicFrames(transport_version())) {
-    EXPECT_CALL(session_, OnCanCreateNewOutgoingStream()).Times(1);
+    EXPECT_CALL(session_, OnCanCreateNewOutgoingStream(false)).Times(1);
   }
   session_.OnRstStream(rst1);
 }
diff --git a/quic/core/quic_stream_id_manager.cc b/quic/core/quic_stream_id_manager.cc
index 8b8ff90..f384776 100644
--- a/quic/core/quic_stream_id_manager.cc
+++ b/quic/core/quic_stream_id_manager.cc
@@ -63,7 +63,7 @@
   // available.
   if (outgoing_stream_count_ == current_outgoing_max_streams &&
       current_outgoing_max_streams < outgoing_max_streams_) {
-    session_->OnCanCreateNewOutgoingStream();
+    session_->OnCanCreateNewOutgoingStream(unidirectional_);
   }
   return true;
 }
diff --git a/quic/tools/quic_simple_server_session.cc b/quic/tools/quic_simple_server_session.cc
index 247e263..ad59527 100644
--- a/quic/tools/quic_simple_server_session.cc
+++ b/quic/tools/quic_simple_server_session.cc
@@ -226,7 +226,8 @@
   }
 }
 
-void QuicSimpleServerSession::OnCanCreateNewOutgoingStream() {
+void QuicSimpleServerSession::OnCanCreateNewOutgoingStream(
+    bool /*unidirectional*/) {
   HandlePromisedPushRequests();
 }
 }  // namespace quic
diff --git a/quic/tools/quic_simple_server_session.h b/quic/tools/quic_simple_server_session.h
index 0ca0e6f..d8cd6b5 100644
--- a/quic/tools/quic_simple_server_session.h
+++ b/quic/tools/quic_simple_server_session.h
@@ -78,7 +78,7 @@
       QuicStreamId original_stream_id,
       const spdy::SpdyHeaderBlock& original_request_headers);
 
-  void OnCanCreateNewOutgoingStream() override;
+  void OnCanCreateNewOutgoingStream(bool unidirectional) override;
 
  protected:
   // QuicSession methods: